diff --git a/pyghmi/exceptions.py b/pyghmi/exceptions.py index a9e2b803..8de693f5 100644 --- a/pyghmi/exceptions.py +++ b/pyghmi/exceptions.py @@ -2,7 +2,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright 2013 IBM Corporation -# Copyright 2015 Lenovo +# Copyright 2015-2017 Lenovo # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -35,6 +35,12 @@ class UnrecognizedCertificate(Exception): self.certdata = certdata +class TemporaryError(Exception): + # A temporary condition that should clear, but warrants reporting to the + # caller + pass + + class InvalidParameterValue(PyghmiException): pass diff --git a/pyghmi/ipmi/oem/lenovo/imm.py b/pyghmi/ipmi/oem/lenovo/imm.py index 5a9dc25d..fbabd78f 100644 --- a/pyghmi/ipmi/oem/lenovo/imm.py +++ b/pyghmi/ipmi/oem/lenovo/imm.py @@ -69,6 +69,7 @@ class IMMClient(object): def __init__(self, ipmicmd): self.ipmicmd = weakref.proxy(ipmicmd) + self.updating = False self.imm = ipmicmd.bmc self.adp_referer = 'https://{0}/designs/imm/index-console.php'.format( self.imm) @@ -222,6 +223,9 @@ class IMMClient(object): def fetch_agentless_firmware(self): adapterdata = self.get_cached_data('lenovo_cached_adapters') if not adapterdata: + if self.updating: + raise pygexc.TemporaryError( + 'Cannot read extended inventory during firmware update') if self.wc: adapterdata = self.wc.grab_json_response( self.ADP_URL, referer=self.adp_referer) @@ -340,6 +344,9 @@ class IMMClient(object): hwmap['Enclosure'] = {'UUID': fixup_uuid(enclosureuuid)} adapterdata = self.get_cached_data('lenovo_cached_adapters') if not adapterdata: + if self.updating: + raise pygexc.TemporaryError( + 'Cannot read extended inventory during firmware update') if self.wc: adapterdata = self.wc.grab_json_response( self.ADP_URL, referer=self.adp_referer) @@ -594,15 +601,21 @@ class XCCClient(IMMClient): def update_firmware(self, filename, data=None, progress=None, bank=None): result = None + if self.updating: + raise pygexc.TemporaryError('Cannot run multiple updates to same ' + 'target concurrently') + self.updating = True try: result = self.update_firmware_backend(filename, data, progress, bank) except Exception: + self.updating = False self._refresh_token() self.wc.grab_json_response('/api/providers/fwupdate', json.dumps( {'UPD_WebCancel': 1})) self.weblogout() raise + self.updating = False self.weblogout() return result