summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pyflashbmc/bmc_update.py163
1 files changed, 154 insertions, 9 deletions
diff --git a/pyflashbmc/bmc_update.py b/pyflashbmc/bmc_update.py
index 50042c1..8e3d43d 100644
--- a/pyflashbmc/bmc_update.py
+++ b/pyflashbmc/bmc_update.py
@@ -4,6 +4,8 @@ import gobject
import dbus
import dbus.service
import dbus.mainloop.glib
+import subprocess
+import tempfile
import shutil
import tarfile
import os
@@ -14,6 +16,9 @@ OBJ_NAME = '/org/openbmc/control/flash/bmc'
FLASH_INTF = 'org.openbmc.Flash'
DOWNLOAD_INTF = 'org.openbmc.managers.Download'
+BMC_DBUS_NAME = 'org.openbmc.control.Bmc'
+BMC_OBJ_NAME = '/org/openbmc/control/bmc0'
+
UPDATE_PATH = '/run/initramfs'
@@ -36,19 +41,23 @@ class BmcFlashControl(DbusProperties,DbusObjectManager):
self.Set(DBUS_NAME,"restore_application_defaults",False)
self.Set(DBUS_NAME,"update_kernel_and_apps",False)
self.Set(DBUS_NAME,"clear_persistent_files",False)
-
+ self.Set(DBUS_NAME,"auto_apply",False)
+
bus.add_signal_receiver(self.download_error_handler,signal_name = "DownloadError")
bus.add_signal_receiver(self.download_complete_handler,signal_name = "DownloadComplete")
+ self.update_process = None
+ self.progress_name = None
+
self.InterfacesAdded(name,self.properties)
@dbus.service.method(DBUS_NAME,
in_signature='ss', out_signature='')
def updateViaTftp(self,ip,filename):
- self.TftpDownload(ip,filename)
self.Set(DBUS_NAME,"status","Downloading")
-
+ self.TftpDownload(ip,filename)
+
@dbus.service.method(DBUS_NAME,
in_signature='s', out_signature='')
def update(self,filename):
@@ -101,7 +110,7 @@ class BmcFlashControl(DbusProperties,DbusObjectManager):
except Exception as e:
print e
- self.Set(DBUS_NAME,"status","Update Error")
+ self.Set(DBUS_NAME,"status","Unpack Error")
return
try:
@@ -138,12 +147,148 @@ class BmcFlashControl(DbusProperties,DbusObjectManager):
except Exception as e:
print e
- self.Set(DBUS_NAME,"status","Update Error")
-
-
+ self.Set(DBUS_NAME,"status","Unpack Error")
+
+ self.Verify()
+
+ def Verify(self):
+ self.Set(DBUS_NAME,"status","Checking Image")
+ try:
+ subprocess.check_call([
+ "/run/initramfs/update",
+ "--no-flash",
+ "--no-save-files",
+ "--no-restore-files",
+ "--no-clean-saved-files" ])
+
+ self.Set(DBUS_NAME,"status","Image ready to apply.")
+ if (self.Get(DBUS_NAME,"auto_apply")):
+ self.Apply()
+ except:
+ self.Set(DBUS_NAME,"auto_apply",False)
+ try:
+ subprocess.check_output([
+ "/run/initramfs/update",
+ "--no-flash",
+ "--ignore-mount",
+ "--no-save-files",
+ "--no-restore-files",
+ "--no-clean-saved-files" ],
+ stderr = subprocess.STDOUT)
+ self.Set(DBUS_NAME,"status","Deferred for mounted filesystem. reboot BMC to apply.")
+ except subprocess.CalledProcessError as e:
+ self.Set(DBUS_NAME,"status","Verify error: %s"
+ % e.output)
+ except OSError as e:
+ self.Set(DBUS_NAME,"status","Verify error: problem calling update: %s" % e.strerror)
+
+
+ def Cleanup(self):
+ if self.progress_name:
+ try:
+ os.unlink(self.progress_name)
+ self.progress_name = None
+ except oserror as e:
+ if e.errno == EEXIST:
+ pass
+ raise
+ self.update_process = None
+ self.Set(DBUS_NAME,"status","Idle")
+
+ @dbus.service.method(DBUS_NAME,
+ in_signature='', out_signature='')
+ def Abort(self):
+ if self.update_process:
+ try:
+ self.update_process.kill()
+ except:
+ pass
+ for file in os.listdir(UPDATE_PATH):
+ if file.startswith('image-'):
+ os.unlink(os.path.join(UPDATE_PATH,file))
+
+ self.Cleanup();
+
+ @dbus.service.method(DBUS_NAME,
+ in_signature='', out_signature='s')
+ def GetUpdateProgress(self):
+ msg = ""
+
+ if self.update_process and self.update_process.returncode is None:
+ self.update_process.poll()
+
+ if (self.update_process is None):
+ pass
+ elif (self.update_process.returncode > 0):
+ self.Set(DBUS_NAME,"status","Apply failed")
+ elif (self.update_process.returncode is None):
+ pass
+ else: # (self.update_process.returncode == 0)
+ files = ""
+ for file in os.listdir(UPDATE_PATH):
+ if file.startswith('image-'):
+ files = files + file;
+ if files == "":
+ msg = "Apply Complete. Reboot to take effect."
+ else:
+ msg = "Apply Incomplete, Remaining:" + files
+ self.Set(DBUS_NAME,"status", msg)
+
+ msg = self.Get(DBUS_NAME,"status") + "\n";
+ if self.progress_name:
+ try:
+ prog = open(self.progress_name,'r')
+ for line in prog:
+ # strip off initial sets of xxx\r here
+ # ignore crlf at the end
+ # cr will be -1 if no '\r' is found
+ cr = line.rfind("\r", 0, -2)
+ msg = msg + line[cr + 1: ]
+ except OSError as e:
+ if (e.error == EEXIST):
+ pass
+ raise
+ return msg
+
+ @dbus.service.method(DBUS_NAME,
+ in_signature='', out_signature='')
+ def Apply(self):
+ progress = None
+ self.Set(DBUS_NAME,"status","Writing images to flash")
+ try:
+ progress = tempfile.NamedTemporaryFile(
+ delete = False, prefix="progress." )
+ self.progress_name = progress.name
+ self.update_process = subprocess.Popen([
+ "/run/initramfs/update" ],
+ stdout = progress.file,
+ stderr = subprocess.STDOUT )
+ except Exception as e:
+ try:
+ progress.close()
+ os.unlink(progress.name)
+ self.progress_name = None
+ except:
+ pass
+ raise
+
+ try:
+ progress.close()
+ except:
+ pass
+
+ @dbus.service.method(DBUS_NAME,
+ in_signature='', out_signature='')
+ def PrepareForUpdate(self):
+ subprocess.call([
+ "fw_setenv",
+ "openbmconce",
+ "copy-files-to-ram copy-base-filesystem-to-ram"])
+ self.Set(DBUS_NAME,"status","Switch to update mode in progress")
+ o = bus.get_object(BMC_DBUS_NAME, BMC_OBJ_NAME)
+ intf = dbus.Interface(o, BMC_DBUS_NAME)
+ intf.warmReset()
- self.Set(DBUS_NAME,"status","Update Success. Please reboot.")
-
if __name__ == '__main__':
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
OpenPOWER on IntegriCloud