summaryrefslogtreecommitdiffstats
path: root/module/obmc/wsgi/apps
diff options
context:
space:
mode:
authorAdriana Kobylak <anoo@us.ibm.com>2018-03-12 13:05:50 -0500
committerAdriana Kobylak <anoo@us.ibm.com>2018-04-10 10:37:59 -0500
commit53693891092b5aa333caf636c91dd0c643153780 (patch)
tree06cf6d037c2014d484171c68780fb184a7495049 /module/obmc/wsgi/apps
parentfe3a099b901cf376f3b965246aa337c6035d75f0 (diff)
downloadphosphor-rest-server-53693891092b5aa333caf636c91dd0c643153780.tar.gz
phosphor-rest-server-53693891092b5aa333caf636c91dd0c643153780.zip
rest_dbus: upload: Return version id
In the put/post upload handler, subscribe to the signal for InterfacesAdded to the software path and return the version id which is the last item of the path, wait up to 10 seconds for the new software D-Bus object to be created. Tested: https://${bmc}/upload/image method returns the version id: Before: { "data": null, "message": "200 OK", "status": "ok" } After: { "data": "84fb16be", "message": "200 OK", "status": "ok" } Change-Id: I307079f9a3b8f05bc42bc77c89e7976920c668a5 Signed-off-by: Adriana Kobylak <anoo@us.ibm.com>
Diffstat (limited to 'module/obmc/wsgi/apps')
-rw-r--r--module/obmc/wsgi/apps/rest_dbus.py62
1 files changed, 57 insertions, 5 deletions
diff --git a/module/obmc/wsgi/apps/rest_dbus.py b/module/obmc/wsgi/apps/rest_dbus.py
index 03a039d..93cd4de 100644
--- a/module/obmc/wsgi/apps/rest_dbus.py
+++ b/module/obmc/wsgi/apps/rest_dbus.py
@@ -50,6 +50,7 @@ DBUS_UNKNOWN_METHOD = 'org.freedesktop.DBus.Error.UnknownMethod'
DBUS_INVALID_ARGS = 'org.freedesktop.DBus.Error.InvalidArgs'
DBUS_TYPE_ERROR = 'org.freedesktop.DBus.Python.TypeError'
DELETE_IFACE = 'xyz.openbmc_project.Object.Delete'
+SOFTWARE_PATH = '/xyz/openbmc_project/software'
_4034_msg = "The specified %s cannot be %s: '%s'"
@@ -716,11 +717,38 @@ class ImageUploadUtils:
file_loc = '/tmp/images'
file_prefix = 'img'
file_suffix = ''
+ signal = None
@classmethod
def do_upload(cls, filename=''):
+ def cleanup():
+ os.close(handle)
+ if cls.signal:
+ cls.signal.remove()
+ cls.signal = None
+
+ def signal_callback(path, a, **kw):
+ # Just interested on the first Version interface created which is
+ # triggered when the file is uploaded. This helps avoid getting the
+ # wrong information for multiple upload requests in a row.
+ if "xyz.openbmc_project.Software.Version" in a and \
+ "xyz.openbmc_project.Software.Activation" not in a:
+ paths.append(path)
+
+ while cls.signal:
+ # Serialize uploads by waiting for the signal to be cleared.
+ # This makes it easier to ensure that the version information
+ # is the right one instead of the data from another upload request.
+ gevent.sleep(1)
if not os.path.exists(cls.file_loc):
abort(500, "Error Directory not found")
+ paths = []
+ bus = dbus.SystemBus()
+ cls.signal = bus.add_signal_receiver(
+ signal_callback,
+ dbus_interface=dbus.BUS_DAEMON_IFACE + '.ObjectManager',
+ signal_name='InterfacesAdded',
+ path=SOFTWARE_PATH)
if not filename:
handle, filename = tempfile.mkstemp(cls.file_suffix,
cls.file_prefix, cls.file_loc)
@@ -731,12 +759,36 @@ class ImageUploadUtils:
file_contents = request.body.read()
request.body.close()
os.write(handle, file_contents)
+ # Close file after writing, the image manager process watches for
+ # the close event to know the upload is complete.
+ os.close(handle)
except (IOError, ValueError) as e:
+ cleanup()
abort(400, str(e))
- except:
+ except Exception:
+ cleanup()
abort(400, "Unexpected Error")
- finally:
- os.close(handle)
+ loop = gobject.MainLoop()
+ gcontext = loop.get_context()
+ count = 0
+ version_id = ''
+ while loop is not None:
+ try:
+ if gcontext.pending():
+ gcontext.iteration()
+ if not paths:
+ gevent.sleep(1)
+ else:
+ version_id = os.path.basename(paths.pop())
+ break
+ count += 1
+ if count == 10:
+ break
+ except Exception:
+ break
+ cls.signal.remove()
+ cls.signal = None
+ return version_id
class ImagePostHandler(RouteHandler):
@@ -751,7 +803,7 @@ class ImagePostHandler(RouteHandler):
app, bus, self.verbs, self.rules, self.content_type)
def do_post(self, filename=''):
- ImageUploadUtils.do_upload()
+ return ImageUploadUtils.do_upload()
def find(self, **kw):
pass
@@ -873,7 +925,7 @@ class ImagePutHandler(RouteHandler):
app, bus, self.verbs, self.rules, self.content_type)
def do_put(self, filename=''):
- ImageUploadUtils.do_upload(filename)
+ return ImageUploadUtils.do_upload(filename)
def find(self, **kw):
pass
OpenPOWER on IntegriCloud