rest_dbus: implement route '/upload/image'

Implement a route named '/upload/image' to be able to upload software upgrade
images to the BMC.

A typical upload via cURL would look like this :
'curl <options> -X POST -T <file_to_upload> https://<bmc_IP>/upload/image'.

The uploaded files are stored at /tmp/images/. The filename of the
uploaded file would be 'imageN', with N starting at 0.

Change-Id: I183f50a108791ef8e70b50fd5e331310240d7a78
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
diff --git a/module/obmc/wsgi/apps/rest_dbus.py b/module/obmc/wsgi/apps/rest_dbus.py
index e83d933..6ba2e28 100644
--- a/module/obmc/wsgi/apps/rest_dbus.py
+++ b/module/obmc/wsgi/apps/rest_dbus.py
@@ -26,6 +26,7 @@
 import spwd
 import grp
 import crypt
+import tempfile
 
 DBUS_UNKNOWN_INTERFACE = 'org.freedesktop.UnknownInterface'
 DBUS_UNKNOWN_INTERFACE_ERROR = 'org.freedesktop.DBus.Error.UnknownInterface'
@@ -531,6 +532,39 @@
         pass
 
 
+class ImageUploadHandler(RouteHandler):
+    ''' Handles the /upload route. '''
+
+    verbs = ['POST']
+    rules = ['/upload/image']
+    content_type = 'application/octet-stream'
+    file_loc = '/tmp/images'
+    file_prefix = 'img'
+    file_suffix = ''
+
+    def __init__(self, app, bus):
+        super(ImageUploadHandler, self).__init__(
+            app, bus, self.verbs, self.rules, self.content_type)
+
+    def do_post(self, **kw):
+        self.do_upload(**kw)
+
+    def do_upload(self, **kw):
+        if not os.path.exists(self.file_loc):
+            os.makedirs(self.file_loc)
+        handle, filename = tempfile.mkstemp(self.file_suffix,
+                                            self.file_prefix, self.file_loc)
+
+        with os.fdopen(handle, "w") as fd:
+            fd.write(request.body.read())
+
+    def find(self, **kw):
+        pass
+
+    def setup(self, **kw):
+        pass
+
+
 class AuthorizationPlugin(object):
     ''' Invokes an optional list of authorization callbacks. '''
 
@@ -836,6 +870,7 @@
         self.method_handler = MethodHandler(self, self.bus)
         self.property_handler = PropertyHandler(self, self.bus)
         self.schema_handler = SchemaHandler(self, self.bus)
+        self.image_upload_handler = ImageUploadHandler(self, self.bus)
         self.instance_handler = InstanceHandler(self, self.bus)
 
     def install_handlers(self):
@@ -846,6 +881,7 @@
         self.method_handler.install()
         self.property_handler.install()
         self.schema_handler.install()
+        self.image_upload_handler.install()
         # this has to come last, since it matches everything
         self.instance_handler.install()