class BlobStore2(object): """Blob store 2 class""" def __init__(self): lib = self.gethprestchifhandle() self.channel = HpIlo(dll=lib) self.max_retries = 3 def __del__(self): """Blob store 2 close channel function""" if hasattr(self, 'channel'): self.channel.close() def create(self, key, namespace): """Create the blob :param key: The blob key to create. :type key: str. :param namespace: The blob namespace to create the key in. :type namespace: str. """ lib = self.gethprestchifhandle() lib.create_not_blobentry.argtypes = [c_char_p, c_char_p] lib.create_not_blobentry.restype = POINTER(c_ubyte) name = create_string_buffer(key.encode('utf-8')) namespace = create_string_buffer(namespace.encode('utf-8')) ptr = lib.create_not_blobentry(name, namespace) data = ptr[:lib.size_of_createRequest()] data = bytearray(data) resp = self._send_receive_raw(data) errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if not (errorcode == BlobReturnCodes.SUCCESS or \ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def get_info(self, key, namespace, retries=0): """Get information for a particular blob :param key: The blob key to retrieve. :type key: str. :param namespace: The blob namespace to retrieve the key from. :type namespace: str. """ lib = self.gethprestchifhandle() lib.get_info.argtypes = [c_char_p, c_char_p] lib.get_info.restype = POINTER(c_ubyte) name = create_string_buffer(key.encode('utf-8')) namspace = create_string_buffer(namespace.encode('utf-8')) ptr = lib.get_info(name, namspace) data = ptr[:lib.size_of_infoRequest()] data = bytearray(data) resp = self._send_receive_raw(data) errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if errorcode == BlobReturnCodes.BADPARAMETER: if retries < self.max_retries: self.get_info(key=key, namespace=namespace, retries=\ retries+1) else: raise Blob2OverrideError(errorcode) elif errorcode == BlobReturnCodes.NOTFOUND: raise BlobNotFoundError(key, namespace) if not (errorcode == BlobReturnCodes.SUCCESS or \ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) response = resp[lib.size_of_responseHeaderBlob():] self.unloadchifhandle(lib) return response def read(self, key, namespace, retries=0): """Read a particular blob :param key: The blob key to be read. :type key: str. :param namespace: The blob namespace to read the key from. :type namespace: str. """ lib = self.gethprestchifhandle() maxread = lib.max_read_size() readsize = lib.size_of_readRequest() readhead = lib.size_of_responseHeaderBlob() self.unloadchifhandle(lib) blob_info = self.get_info(key, namespace) blobsize = struct.unpack("<I", bytes(blob_info[0:4]))[0] bytes_read = 0 data = bytearray() while bytes_read < blobsize: if (maxread - readsize) < (blobsize - bytes_read): count = maxread - readsize else: count = blobsize - bytes_read read_block_size = bytes_read recvpkt = self.read_fragment(key, namespace, read_block_size, count) newreadsize = readhead + 4 bytesread = struct.unpack("<I", bytes(recvpkt[readhead:\ (newreadsize)]))[0] if bytesread == 0: if retries < self.max_retries: data = self.read(key=key, namespace=namespace, retries=\ retries+1) return data else: raise BlobRetriesExhaustedError() data.extend(recvpkt[newreadsize:newreadsize + bytesread]) bytes_read += bytesread return data def read_fragment(self, key, namespace, offset=0, count=1): """Fragmented version of read function for large blobs :param key: The blob key to be read. :type key: str. :param namespace: The blob namespace to read the key from. :type namespace: str. :param offset: The data offset for the current fragmented read. :type key: int. :param count: The data count for the current fragmented read. :type namespace: int. """ lib = self.gethprestchifhandle() lib.read_fragment.argtypes = [c_uint, c_uint, c_char_p, c_char_p] lib.read_fragment.restype = POINTER(c_ubyte) name = create_string_buffer(key.encode('utf-8')) namespace = create_string_buffer(namespace.encode('utf-8')) ptr = lib.read_fragment(offset, count, name, namespace) data = ptr[:lib.size_of_readRequest()] data = bytearray(data) resp = self._send_receive_raw(data) resp = resp + b"\0" * (lib.size_of_readResponse() - len(resp)) return resp def write(self, key, namespace, data=None): """Write a particular blob :param key: The blob key to be written. :type key: str. :param namespace: The blob namespace to write the key in. :type namespace: str. :param data: The blob data to be written. :type data: str. """ lib = self.gethprestchifhandle() maxwrite = lib.max_write_size() writesize = lib.size_of_writeRequest() self.unloadchifhandle(lib) if data: data_length = len(data) bytes_written = 0 while bytes_written < data_length: if (maxwrite - writesize) < (data_length - bytes_written): count = maxwrite - writesize else: count = data_length - bytes_written write_blob_size = bytes_written self.write_fragment(key, namespace=namespace, \ data=data[write_blob_size:write_blob_size+count], \ offset=write_blob_size, count=count) bytes_written += count return self.finalize(key, namespace=namespace) def write_fragment(self, key, namespace, data=None, offset=0, count=1): """Fragmented version of write function for large blobs :param key: The blob key to be written. :type key: str. :param namespace: The blob namespace to write the key in. :type namespace: str. :param data: The blob data to be written to blob. :type data: str. :param offset: The data offset for the current fragmented write. :type key: int. :param count: The data count for the current fragmented write. :type count: int. """ lib = self.gethprestchifhandle() lib.write_fragment.argtypes = [c_uint, c_uint, c_char_p, c_char_p] lib.write_fragment.restype = POINTER(c_ubyte) name = create_string_buffer(key.encode('utf-8')) namespace = create_string_buffer(namespace.encode('utf-8')) ptr = lib.write_fragment(offset, count, name, namespace) sendpacket = ptr[:lib.size_of_writeRequest()] dataarr = bytearray(sendpacket) dataarr.extend(memoryview(data)) resp = self._send_receive_raw(dataarr) errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def delete(self, key, namespace, retries=0): """Delete the blob :param key: The blob key to be deleted. :type key: str. :param namespace: The blob namespace to delete the key from. :type namespace: str. """ lib = self.gethprestchifhandle() lib.delete_blob.argtypes = [c_char_p, c_char_p] lib.delete_blob.restype = POINTER(c_ubyte) name = create_string_buffer(key.encode('utf-8')) namspace = create_string_buffer(namespace.encode('utf-8')) ptr = lib.delete_blob(name, namspace) data = ptr[:lib.size_of_deleteRequest()] data = bytearray(data) resp = self._send_receive_raw(data) errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if errorcode == BlobReturnCodes.BADPARAMETER: if retries < self.max_retries: self.delete(key=key, namespace=namespace, retries=\ retries+1) else: raise Blob2OverrideError(errorcode) elif not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return errorcode def list(self, namespace): """List operation to retrieve all blobs in a given namespace :param namespace: The blob namespace to retrieve the keys from. :type namespace: str. """ lib = self.gethprestchifhandle() lib.list_blob.argtypes = [c_char_p] lib.list_blob.restype = POINTER(c_ubyte) namespace = create_string_buffer(namespace.encode('utf-8')) ptr = lib.list_blob(namespace) data = ptr[:lib.size_of_listRequest()] data = bytearray(data) resp = self._send_receive_raw(data) errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) resp = resp + "\0" * (lib.size_of_listResponse() - len(resp)) self.unloadchifhandle(lib) return resp def finalize(self, key, namespace): """Finalize the blob :param key: The blob key to be finalized. :type key: str. :param namespace: The blob namespace to finalize the key in. :type namespace: str. """ lib = self.gethprestchifhandle() lib.finalize_blob.argtypes = [c_char_p, c_char_p] lib.finalize_blob.restype = POINTER(c_ubyte) name = create_string_buffer(key.encode('utf-8')) namespace = create_string_buffer(namespace.encode('utf-8')) ptr = lib.finalize_blob(name, namespace) data = ptr[:lib.size_of_finalizeRequest()] data = bytearray(data) resp = self._send_receive_raw(data) errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return errorcode def rest_immediate(self, req_data, rqt_key="RisRequest", \ rsp_key="RisResponse", rsp_namespace="volatile"): """Read/write blob via immediate operation :param req_data: The blob data to be read/written. :type req_data: str. :param rqt_key: The blob key to be used for the request data. :type rqt_key: str. :param rsp_key: The blob key to be used for the response data. :type rsp_key: str. :param rsp_namespace: The blob namespace to retrieve the response from. :type rsp_namespace: str. """ rqt_key = ''.join(random.choice(string.ascii_letters + \ string.digits) for _ in range(10)) rsp_key = ''.join(random.choice(string.ascii_letters + \ string.digits) for _ in range(10)) lib = self.gethprestchifhandle() if len(req_data) < (lib.size_of_restImmediateRequest() + \ lib.max_write_size()): lib.rest_immediate.argtypes = [c_uint, c_char_p, c_char_p] lib.rest_immediate.restype = POINTER(c_ubyte) name = create_string_buffer(rsp_key.encode('utf-8')) namespace = create_string_buffer(rsp_namespace.encode('utf-8')) ptr = lib.rest_immediate(len(req_data), name, namespace) sendpacket = ptr[:lib.size_of_restImmediateRequest()] mode = False else: self.create(rqt_key, rsp_namespace) self.write(rqt_key, rsp_namespace, req_data) lib.rest_immediate_blobdesc.argtypes = [c_char_p, c_char_p, \ c_char_p] lib.rest_immediate_blobdesc.restype = POINTER(c_ubyte) name = create_string_buffer(rqt_key.encode('utf-8')) namespace = create_string_buffer(rsp_namespace.encode('utf-8')) rspname = create_string_buffer(rsp_key.encode('utf-8')) ptr = lib.rest_immediate_blobdesc(name, rspname, namespace) sendpacket = ptr[:lib.size_of_restBlobRequest()] mode = True data = bytearray(sendpacket) if not mode: data.extend(req_data) resp = self._send_receive_raw(data) errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if errorcode == BlobReturnCodes.NOTFOUND: raise BlobNotFoundError(rsp_key, rsp_namespace) recvmode = struct.unpack("<I", bytes(resp[12:16]))[0] fixdlen = lib.size_of_restResponseFixed() response = resp[fixdlen:struct.unpack("<I", bytes(resp[16:20]))[0] + \ fixdlen] tmpresponse = None if errorcode == BlobReturnCodes.SUCCESS and not mode: if recvmode == 0: tmpresponse = ''.join(map(chr, response)) elif errorcode == BlobReturnCodes.NOTMODIFIED and not mode: if recvmode == 0: tmpresponse = ''.join(map(chr, response)) elif errorcode == BlobReturnCodes.SUCCESS: if recvmode == 0: tmpresponse = ''.join(map(chr, response)) elif recvmode == 0: raise HpIloError(errorcode) self.unloadchifhandle(lib) if not tmpresponse and recvmode == 1: tmpresponse = self.read(rsp_key, rsp_namespace) try: self.delete(rsp_key, rsp_namespace) except Exception as excp: raise excp else: try: self.delete(rsp_key, rsp_namespace) except Blob2OverrideError as excp: pass except Exception as excp: raise excp return tmpresponse def get_security_state(self): """Get information for the current security state""" lib = self.gethprestchifhandle() lib.get_security_state.argtypes = [] lib.get_security_state.restype = POINTER(c_ubyte) ptr = lib.get_security_state() data = ptr[:lib.size_of_securityStateRequest()] data = bytearray(data) resp = self._send_receive_raw(data) errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if not (errorcode == BlobReturnCodes.SUCCESS or \ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) try: securitystate = struct.unpack("<c", bytes(resp[72]))[0] except: securitystate = int(resp[72]) self.unloadchifhandle(lib) return securitystate def mount_blackbox(self): """Operation to mount the blackbox partition""" lib = self.gethprestchifhandle() lib.blackbox_media_mount.argtypes = [] lib.blackbox_media_mount.restype = POINTER(c_ubyte) ptr = lib.blackbox_media_mount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def absaroka_media_mount(self): """Operation to mount the absaroka repo partition""" lib = self.gethprestchifhandle() lib.absaroka_media_mount.argtypes = [] lib.absaroka_media_mount.restype = POINTER(c_ubyte) ptr = lib.absaroka_media_mount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def gaius_media_mount(self): """Operation to mount the gaius media partition""" lib = self.gethprestchifhandle() lib.gaius_media_mount.argtypes = [] lib.gaius_media_mount.restype = POINTER(c_ubyte) ptr = lib.gaius_media_mount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def vid_media_mount(self): """Operation to mount the gaius media partition""" lib = self.gethprestchifhandle() lib.vid_media_mount.argtypes = [] lib.vid_media_mount.restype = POINTER(c_ubyte) ptr = lib.vid_media_mount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def mountflat(self): """Operation to mount the gaius media partition""" lib = self.gethprestchifhandle() lib.flat_media_mount.argtypes = [] lib.flat_media_mount.restype = POINTER(c_ubyte) ptr = lib.flat_media_mount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def media_unmount(self): """Operation to unmount the media partition""" lib = self.gethprestchifhandle() lib.media_unmount.argtypes = [] lib.media_unmount.restype = POINTER(c_ubyte) ptr = lib.media_unmount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def bb_media_unmount(self): """Operation to unmount the media partition""" lib = self.gethprestchifhandle() lib.bb_media_unmount.argtypes = [] lib.bb_media_unmount.restype = POINTER(c_ubyte) ptr = lib.bb_media_unmount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def vid_media_unmount(self): """Operation to unmount the media partition""" lib = self.gethprestchifhandle() lib.vid_media_unmount.argtypes = [] lib.vid_media_unmount.restype = POINTER(c_ubyte) ptr = lib.vid_media_unmount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def gaius_media_unmount(self): """Operation to unmount the media partition""" lib = self.gethprestchifhandle() lib.gaius_media_unmount.argtypes = [] lib.gaius_media_unmount.restype = POINTER(c_ubyte) ptr = lib.gaius_media_unmount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def absr_media_unmount(self): """Operation to unmount the media partition""" lib = self.gethprestchifhandle() lib.absaroka_media_unmount.argtypes = [] lib.absaroka_media_unmount.restype = POINTER(c_ubyte) ptr = lib.absaroka_media_unmount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def _send_receive_raw(self, indata): """Send and receive raw function for blob operations :param indata: The data to be sent to blob operation. :type indata: str. """ excp = None for _ in range(0, 3): # channel loop for iLO try: resp = self.channel.send_receive_raw(indata, 10) return resp except Exception as exp: self.channel.close() lib = self.gethprestchifhandle() self.channel = HpIlo(dll=lib) excp = exp if excp: raise excp @staticmethod def gethprestchifhandle(): """Multi platform handle for chif hprest library""" excp = None libhandle = None libnames = ["ilorest_chif.dll", "hprest_chif.dll"] if os.name == \ 'nt' else ["ilorest_chif_dev.so", "hprest_chif_dev.so", \ "ilorest_chif.so", "hprest_chif.so"] for libname in libnames: try: libpath = BlobStore2.checkincurrdirectory(libname) libhandle = cdll.LoadLibrary(libpath) if libhandle: break except Exception as exp: excp = exp if libhandle: BlobStore2.setglobalhprestchifrandnumber(libhandle) return libhandle raise ChifDllMissingError(excp) @staticmethod def setglobalhprestchifrandnumber(libbhndl): """Set the random number for the chif handle :param libbhndl: The library handle provided by loading the chif library. :type libbhndl: library handle. """ rndval = random.randint(1, 65535) libbhndl.updaterandval.argtypes = [c_ushort] libbhndl.updaterandval(rndval) @staticmethod def initializecreds(username=None, password=None): """Get chif ready to use high security :param username: The username to login. :type username: str. :param password: The password to login. :type password: str. """ dll = BlobStore2.gethprestchifhandle() if LOGGER.isEnabledFor(logging.DEBUG): dll.enabledebugoutput() dll.ChifInitialize(None) if dll.ChifIsSecurityRequired() > 0: if not username or not password: return False dll.initiate_credentials.argtypes = [c_char_p, c_char_p] dll.initiate_credentials.restype = POINTER(c_ubyte) usernew = create_string_buffer(username.encode('utf-8')) passnew = create_string_buffer(password.encode('utf-8')) dll.initiate_credentials(usernew, passnew) credreturn = dll.ChifVerifyCredentials() if not credreturn == BlobReturnCodes.SUCCESS: if credreturn == hpiloreturncodes.CHIFERR_AccessDenied: raise Blob2SecurityError() else: raise HpIloInitialError("Error %s occurred while trying " \ "to open a channel to iLO" % credreturn) else: #so we don't have extra overhead if we don't have to dll.ChifDisableSecurity() BlobStore2.unloadchifhandle(dll) return True @staticmethod def checkincurrdirectory(libname): """Check if the library is present in current directory. :param libname: The name of the library to search for. :type libname: str.""" libpath = libname if os.path.isfile(os.path.join(os.path.split(sys.executable)[0], libpath)): libpath = os.path.join(os.path.split(sys.executable)[0], libpath) elif os.path.isfile(os.path.join(os.getcwd(), libpath)): libpath = os.path.join(os.getcwd(), libpath) elif os.environ.has_key("LD_LIBRARY_PATH"): paths = os.getenv("LD_LIBRARY_PATH", libpath).split(';') libpath = [os.path.join(pat, libname) for pat in paths if \ os.path.isfile(os.path.join(pat, libname))] libpath = libpath[0] if libpath else libname return libpath @staticmethod def unloadchifhandle(lib): """Release a handle on the chif iLOrest library :param lib: The library handle provided by loading the chif library. :type lib: library handle. """ try: libhandle = lib._handle if os.name == 'nt': windll.kernel32.FreeLibrary(None, handle=libhandle) else: dlclose(libhandle) except Exception: pass
class BlobStore2(object): """Blob store 2 class""" def __init__(self): self.channel = HpIlo() def __del__(self): """Blob store 2 close channel function""" if hasattr(self, 'channel'): self.channel.close() def create(self, key, namespace): """Create the blob :param key: The blob key to create. :type key: str. :param namespace: The blob namespace to create the key in. :type namespace: str. """ lib = self.gethprestchifhandle() lib.create_not_blobentry.argtypes = [c_char_p, c_char_p] lib.create_not_blobentry.restype = POINTER(c_ubyte) name = create_string_buffer(key) namespace = create_string_buffer(namespace) ptr = lib.create_not_blobentry(name, namespace) data = ptr[:lib.size_of_createRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_createResponse()) if len(resp) > lib.size_of_createResponse(): raise Blob2CreateError("create response larger than expected") if len(resp) < lib.size_of_createResponse(): raise Blob2CreateError("create response smaller than expected") errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if not (errorcode == BlobReturnCodes.SUCCESS or \ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def get_info(self, key, namespace): """Get information for a particular blob :param key: The blob key to retrieve. :type key: str. :param namespace: The blob namespace to retrieve the key from. :type namespace: str. """ lib = self.gethprestchifhandle() lib.get_info.argtypes = [c_char_p, c_char_p] lib.get_info.restype = POINTER(c_ubyte) name = create_string_buffer(key) namespace = create_string_buffer(namespace) ptr = lib.get_info(name, namespace) data = ptr[:lib.size_of_infoRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_infoResponse()) if len(resp) > lib.size_of_infoResponse(): raise Blob2InfoError("info response larger than expected") if len(resp) < lib.size_of_infoResponse(): raise Blob2InfoError("info response smaller than expected") errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if errorcode == BlobReturnCodes.NOTFOUND: raise BlobNotFoundError(key, namespace) if not (errorcode == BlobReturnCodes.SUCCESS or \ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) response = resp[lib.size_of_responseHeaderBlob():] self.unloadchifhandle(lib) return response def read(self, key, namespace): """Read a particular blob :param key: The blob key to be read. :type key: str. :param namespace: The blob namespace to read the key from. :type namespace: str. """ lib = self.gethprestchifhandle() maxread = lib.max_read_size() readsize = lib.size_of_readRequest() readhead = lib.size_of_responseHeaderBlob() self.unloadchifhandle(lib) blob_info = self.get_info(key, namespace) blobsize = struct.unpack("<I", bytes(blob_info[0:4]))[0] bytes_read = 0 data = bytearray() while bytes_read < blobsize: if (maxread - readsize) < (blobsize - bytes_read): count = maxread - readsize else: count = blobsize - bytes_read read_block_size = bytes_read recvpkt = self.read_fragment(key, namespace, read_block_size, count) newreadsize = readhead + 4 bytesread = struct.unpack("<I", bytes(recvpkt[readhead:\ (newreadsize)]))[0] data.extend(recvpkt[newreadsize:newreadsize + bytesread]) bytes_read += bytesread return data def read_fragment(self, key, namespace, offset=0, count=1): """Fragmented version of read function for large blobs :param key: The blob key to be read. :type key: str. :param namespace: The blob namespace to read the key from. :type namespace: str. :param offset: The data offset for the current fragmented read. :type key: int. :param count: The data count for the current fragmented read. :type namespace: int. """ lib = self.gethprestchifhandle() lib.read_fragment.argtypes = [c_uint, c_uint, c_char_p, c_char_p] lib.read_fragment.restype = POINTER(c_ubyte) name = create_string_buffer(key) namespace = create_string_buffer(namespace) ptr = lib.read_fragment(offset, count, name, namespace) data = ptr[:lib.size_of_readRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_readResponse()) if len(resp) < lib.size_of_responseHeaderBlob(): raise Blob2ReadError("read fragment response smaller than expected") resp = resp + "\0" * (lib.size_of_readResponse() - len(resp)) return resp def write(self, key, namespace, data=None): """Write a particular blob :param key: The blob key to be written. :type key: str. :param namespace: The blob namespace to write the key in. :type namespace: str. :param data: The blob data to be written. :type data: str. """ lib = self.gethprestchifhandle() maxwrite = lib.max_write_size() writesize = lib.size_of_writeRequest() self.unloadchifhandle(lib) if data: data_length = len(data) bytes_written = 0 while bytes_written < data_length: if (maxwrite - writesize) < (data_length - bytes_written): count = maxwrite - writesize else: count = data_length - bytes_written write_blob_size = bytes_written self.write_fragment(key, namespace=namespace, \ data=data[write_blob_size:write_blob_size+count], \ offset=write_blob_size, count=count) bytes_written += count return self.finalize(key, namespace=namespace) def write_fragment(self, key, namespace, data=None, offset=0, count=1): """Fragmented version of write function for large blobs :param key: The blob key to be written. :type key: str. :param namespace: The blob namespace to write the key in. :type namespace: str. :param data: The blob data to be written to blob. :type data: str. :param offset: The data offset for the current fragmented write. :type key: int. :param count: The data count for the current fragmented write. :type count: int. """ lib = self.gethprestchifhandle() lib.write_fragment.argtypes = [c_uint, c_uint, c_char_p, c_char_p] lib.write_fragment.restype = POINTER(c_ubyte) name = create_string_buffer(key) namespace = create_string_buffer(namespace) ptr = lib.write_fragment(offset, count, name, namespace) sendpacket = ptr[:lib.size_of_writeRequest()] dataarr = bytearray(sendpacket) dataarr.extend(buffer(data)) resp = self._send_receive_raw(dataarr, lib.size_of_writeResponse()) if len(resp) < lib.size_of_writeResponse(): raise Blob2WriteError("write fragment response larger than " \ "expected") errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def delete(self, key, namespace): """Delete the blob :param key: The blob key to be deleted. :type key: str. :param namespace: The blob namespace to delete the key from. :type namespace: str. """ lib = self.gethprestchifhandle() lib.delete_blob.argtypes = [c_char_p, c_char_p] lib.delete_blob.restype = POINTER(c_ubyte) name = create_string_buffer(key) namespace = create_string_buffer(namespace) ptr = lib.delete_blob(name, namespace) data = ptr[:lib.size_of_deleteRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_deleteResponse()) if len(resp) > lib.size_of_deleteResponse(): raise Blob2DeleteError("delete response larger than expected") if len(resp) < lib.size_of_deleteResponse(): raise Blob2DeleteError("delete response smaller than expected") errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return errorcode def list(self, namespace): """List operation to retrieve all blobs in a given namespace :param namespace: The blob namespace to retrieve the keys from. :type namespace: str. """ lib = self.gethprestchifhandle() lib.list_blob.argtypes = [c_char_p] lib.list_blob.restype = POINTER(c_ubyte) namespace = create_string_buffer(namespace) ptr = lib.list_blob(namespace) data = ptr[:lib.size_of_listRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_listResponse()) if len(resp) < lib.size_of_listResponseFixed(): raise Blob2ListError("list response smaller than expected") errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) resp = resp + "\0" * (lib.size_of_listResponse() - len(resp)) self.unloadchifhandle(lib) return resp def finalize(self, key, namespace): """Finalize the blob :param key: The blob key to be finalized. :type key: str. :param namespace: The blob namespace to finalize the key in. :type namespace: str. """ lib = self.gethprestchifhandle() lib.finalize_blob.argtypes = [c_char_p, c_char_p] lib.finalize_blob.restype = POINTER(c_ubyte) name = create_string_buffer(key) namespace = create_string_buffer(namespace) ptr = lib.finalize_blob(name, namespace) data = ptr[:lib.size_of_finalizeRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_finalizeResponse()) if len(resp) > lib.size_of_finalizeResponse(): raise Blob2FinalizeError("finalize response smaller than expected") if len(resp) < lib.size_of_finalizeResponse(): raise Blob2FinalizeError("finalize response smaller than expected") errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return errorcode def rest_immediate(self, req_data, rqt_key="RisRequest", \ rsp_key="RisResponse", \ rsp_namespace="volatile"): """Read/write blob via immediate operation :param req_data: The blob data to be read/written. :type req_data: str. :param rqt_key: The blob key to be used for the request data. :type rqt_key: str. :param rsp_key: The blob key to be used for the response data. :type rsp_key: str. :param rsp_namespace: The blob namespace to retrieve the response from. :type rsp_namespace: str. """ lib = self.gethprestchifhandle() if len(req_data) < (lib.size_of_restImmediateRequest() + \ lib.max_write_size()): lib.rest_immediate.argtypes = [c_uint, c_char_p, c_char_p] lib.rest_immediate.restype = POINTER(c_ubyte) name = create_string_buffer(rsp_key) namespace = create_string_buffer(rsp_namespace) ptr = lib.rest_immediate(len(req_data), name, namespace) sendpacket = ptr[:lib.size_of_restImmediateRequest()] mode = False else: self.create(rqt_key, rsp_namespace) self.write(rqt_key, rsp_namespace, req_data) lib.rest_immediate_blobdesc.argtypes = [c_char_p, c_char_p, \ c_char_p] lib.rest_immediate_blobdesc.restype = POINTER(c_ubyte) name = create_string_buffer(rqt_key) namespace = create_string_buffer(rsp_namespace) rspname = create_string_buffer(rsp_key) ptr = lib.rest_immediate_blobdesc(name, rspname, namespace) sendpacket = ptr[:lib.size_of_restBlobRequest()] mode = True data = bytearray(sendpacket) if not mode: data.extend(req_data) resp = self._send_receive_raw(data, lib.size_of_restResponse()) errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if errorcode == BlobReturnCodes.NOTFOUND: raise BlobNotFoundError(rsp_key, rsp_namespace) recvmode = struct.unpack("<I", bytes(resp[12:16]))[0] fixdlen = lib.size_of_restResponseFixed() response = resp[fixdlen:struct.unpack("<I", bytes(resp[16:20]))[0] + \ fixdlen] tmpresponse = None if errorcode == BlobReturnCodes.SUCCESS and not mode: if recvmode == 0: tmpresponse = ''.join(map(chr, response)) elif errorcode == BlobReturnCodes.NOTMODIFIED and not mode: if recvmode == 0: tmpresponse = ''.join(map(chr, response)) elif errorcode == BlobReturnCodes.SUCCESS: if recvmode == 0: tmpresponse = ''.join(map(chr, response)) elif recvmode == 0: raise HpIloError(errorcode) self.unloadchifhandle(lib) if not tmpresponse and recvmode == 1: tmpresponse = self.read(rsp_key, rsp_namespace) self.delete(rsp_key, rsp_namespace) else: self.delete(rsp_key, rsp_namespace) return tmpresponse def mount_blackbox(self): """Operation to mount the blackbox partition""" lib = self.gethprestchifhandle() lib.blackbox_media_mount.argtypes = [] lib.blackbox_media_mount.restype = POINTER(c_ubyte) ptr = lib.blackbox_media_mount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_embeddedMediaResponse()) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def absaroka_media_mount(self): """Operation to mount the absaroka repo partition""" lib = self.gethprestchifhandle() lib.absaroka_media_mount.argtypes = [] lib.absaroka_media_mount.restype = POINTER(c_ubyte) ptr = lib.absaroka_media_mount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_embeddedMediaResponse()) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def gaius_media_mount(self): """Operation to mount the gaius media partition""" lib = self.gethprestchifhandle() lib.gaius_media_mount.argtypes = [] lib.gaius_media_mount.restype = POINTER(c_ubyte) ptr = lib.gaius_media_mount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_embeddedMediaResponse()) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def media_unmount(self): """Operation to unmount the media partition""" lib = self.gethprestchifhandle() lib.media_unmount.argtypes = [] lib.media_unmount.restype = POINTER(c_ubyte) ptr = lib.media_unmount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_embeddedMediaResponse()) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def _send_receive_raw(self, indata, datarecv=0): """Send and receive raw function for blob operations :param indata: The data to be sent to blob operation. :type indata: str. :param datarecv: The expected size of the blob operation response. :type datarecv: int. """ resp = self.channel.send_receive_raw(indata, 3, datarecv) return resp @staticmethod def gethprestchifhandle(): """Multi platform handle for chif hprest library""" try: if os.name == 'nt': libpath = BlobStore2.checkincurrdirectory('hprest_chif.dll') libhandle = cdll.LoadLibrary(libpath) else: try: libpath = BlobStore2.checkincurrdirectory('hprest_chif_dev.so') libhandle = cdll.LoadLibrary(libpath) except: libpath = BlobStore2.checkincurrdirectory('hprest_chif.so') libhandle = cdll.LoadLibrary(libpath) except Exception as excp: raise ChifDllMissingError(excp) return libhandle @staticmethod def checkincurrdirectory(libname): """Check if the library is present in current directory.""" libpath = libname if os.path.isfile(os.path.join(os.path.split(sys.executable)[0], libpath)): libpath = os.path.join(os.path.split(sys.executable)[0], libpath) elif os.path.isfile(os.path.join(os.getcwd(), libpath)): libpath = os.path.join(os.getcwd(), libpath) return libpath @staticmethod def unloadchifhandle(lib): """Release a handle on the chif hprest library :param lib: The library handle provided by loading the chif library. :type lib: library handle. """ try: libhandle = lib._handle if os.name == 'nt': windll.kernel32.FreeLibrary(None, handle=libhandle) else: dlclose(libhandle) except Exception: pass
class BlobStore2(object): """Blob store 2 class""" def __init__(self): self.channel = HpIlo() def __del__(self): """Blob store 2 close channel function""" if hasattr(self, 'channel'): self.channel.close() def create(self, key, namespace): """Create the blob :param key: The blob key to create. :type key: str. :param namespace: The blob namespace to create the key in. :type namespace: str. """ lib = self.gethprestchifhandle() lib.create_not_blobentry.argtypes = [c_char_p, c_char_p] lib.create_not_blobentry.restype = POINTER(c_ubyte) name = create_string_buffer(key) namespace = create_string_buffer(namespace) ptr = lib.create_not_blobentry(name, namespace) data = ptr[:lib.size_of_createRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_createResponse()) if len(resp) > lib.size_of_createResponse(): raise Blob2CreateError("create response larger than expected") if len(resp) < lib.size_of_createResponse(): raise Blob2CreateError("create response smaller than expected") errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if not (errorcode == BlobReturnCodes.SUCCESS or \ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def createbc(self, key, namespace): """Create the blob :param key: The blob key to create. :type key: str. :param namespace: The blob namespace to create the key in. :type namespace: str. """ lib = self.gethprestchifhandle() lib.create_not_blobentrybc.argtypes = [c_char_p, c_char_p] lib.create_not_blobentrybc.restype = POINTER(c_ubyte) name = create_string_buffer(key) namespace = create_string_buffer(namespace) ptr = lib.create_not_blobentrybc(name, namespace) data = ptr[:lib.size_of_srbuf()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_srbuf()) if len(resp) > lib.size_of_srbuf(): raise Blob2CreateError("create response larger than expected") if len(resp) < lib.size_of_srbuf(): raise Blob2CreateError("create response smaller than expected") errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if not (errorcode == BlobReturnCodes.SUCCESS or \ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def get_info(self, key, namespace): """Get information for a particular blob :param key: The blob key to retrieve. :type key: str. :param namespace: The blob namespace to retrieve the key from. :type namespace: str. """ lib = self.gethprestchifhandle() lib.get_info.argtypes = [c_char_p, c_char_p] lib.get_info.restype = POINTER(c_ubyte) name = create_string_buffer(key) namespace = create_string_buffer(namespace) ptr = lib.get_info(name, namespace) data = ptr[:lib.size_of_infoRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_infoResponse()) if len(resp) > lib.size_of_infoResponse(): raise Blob2InfoError("info response larger than expected") if len(resp) < lib.size_of_infoResponse(): raise Blob2InfoError("info response smaller than expected") errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if errorcode == BlobReturnCodes.BADPARAMETER: raise Blob2OverrideError(errorcode) elif errorcode == BlobReturnCodes.NOTFOUND: raise BlobNotFoundError(key, namespace) if not (errorcode == BlobReturnCodes.SUCCESS or \ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) response = resp[lib.size_of_responseHeaderBlob():] self.unloadchifhandle(lib) return response def read(self, key, namespace): """Read a particular blob :param key: The blob key to be read. :type key: str. :param namespace: The blob namespace to read the key from. :type namespace: str. """ lib = self.gethprestchifhandle() maxread = lib.max_read_size() readsize = lib.size_of_readRequest() readhead = lib.size_of_responseHeaderBlob() self.unloadchifhandle(lib) blob_info = self.get_info(key, namespace) blobsize = struct.unpack("<I", bytes(blob_info[0:4]))[0] bytes_read = 0 data = bytearray() while bytes_read < blobsize: if (maxread - readsize) < (blobsize - bytes_read): count = maxread - readsize else: count = blobsize - bytes_read read_block_size = bytes_read recvpkt = self.read_fragment(key, namespace, read_block_size, count) newreadsize = readhead + 4 bytesread = struct.unpack("<I", bytes(recvpkt[readhead:\ (newreadsize)]))[0] if bytesread == 0: raise Blob2OverrideError() data.extend(recvpkt[newreadsize:newreadsize + bytesread]) bytes_read += bytesread return data def read_fragment(self, key, namespace, offset=0, count=1): """Fragmented version of read function for large blobs :param key: The blob key to be read. :type key: str. :param namespace: The blob namespace to read the key from. :type namespace: str. :param offset: The data offset for the current fragmented read. :type key: int. :param count: The data count for the current fragmented read. :type namespace: int. """ lib = self.gethprestchifhandle() lib.read_fragment.argtypes = [c_uint, c_uint, c_char_p, c_char_p] lib.read_fragment.restype = POINTER(c_ubyte) name = create_string_buffer(key) namespace = create_string_buffer(namespace) ptr = lib.read_fragment(offset, count, name, namespace) data = ptr[:lib.size_of_readRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_readResponse()) if len(resp) < lib.size_of_responseHeaderBlob(): raise Blob2ReadError("read fragment response smaller than expected") resp = resp + "\0" * (lib.size_of_readResponse() - len(resp)) return resp def write(self, key, namespace, data=None): """Write a particular blob :param key: The blob key to be written. :type key: str. :param namespace: The blob namespace to write the key in. :type namespace: str. :param data: The blob data to be written. :type data: str. """ lib = self.gethprestchifhandle() maxwrite = lib.max_write_size() writesize = lib.size_of_writeRequest() self.unloadchifhandle(lib) if data: data_length = len(data) bytes_written = 0 while bytes_written < data_length: if (maxwrite - writesize) < (data_length - bytes_written): count = maxwrite - writesize else: count = data_length - bytes_written write_blob_size = bytes_written self.write_fragment(key, namespace=namespace, \ data=data[write_blob_size:write_blob_size+count], \ offset=write_blob_size, count=count) bytes_written += count return self.finalize(key, namespace=namespace) def write_fragment(self, key, namespace, data=None, offset=0, count=1): """Fragmented version of write function for large blobs :param key: The blob key to be written. :type key: str. :param namespace: The blob namespace to write the key in. :type namespace: str. :param data: The blob data to be written to blob. :type data: str. :param offset: The data offset for the current fragmented write. :type key: int. :param count: The data count for the current fragmented write. :type count: int. """ lib = self.gethprestchifhandle() lib.write_fragment.argtypes = [c_uint, c_uint, c_char_p, c_char_p] lib.write_fragment.restype = POINTER(c_ubyte) name = create_string_buffer(key) namespace = create_string_buffer(namespace) ptr = lib.write_fragment(offset, count, name, namespace) sendpacket = ptr[:lib.size_of_writeRequest()] dataarr = bytearray(sendpacket) dataarr.extend(buffer(data)) resp = self._send_receive_raw(dataarr, lib.size_of_writeResponse()) if len(resp) < lib.size_of_writeResponse(): raise Blob2WriteError("write fragment response larger than " \ "expected") errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def delete(self, key, namespace): """Delete the blob :param key: The blob key to be deleted. :type key: str. :param namespace: The blob namespace to delete the key from. :type namespace: str. """ lib = self.gethprestchifhandle() lib.delete_blob.argtypes = [c_char_p, c_char_p] lib.delete_blob.restype = POINTER(c_ubyte) name = create_string_buffer(key) namespace = create_string_buffer(namespace) ptr = lib.delete_blob(name, namespace) data = ptr[:lib.size_of_deleteRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_deleteResponse()) if len(resp) > lib.size_of_deleteResponse(): raise Blob2DeleteError("delete response larger than expected") if len(resp) < lib.size_of_deleteResponse(): raise Blob2DeleteError("delete response smaller than expected") errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if errorcode == BlobReturnCodes.BADPARAMETER: raise Blob2OverrideError(errorcode) elif not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return errorcode def list(self, namespace): """List operation to retrieve all blobs in a given namespace :param namespace: The blob namespace to retrieve the keys from. :type namespace: str. """ lib = self.gethprestchifhandle() lib.list_blob.argtypes = [c_char_p] lib.list_blob.restype = POINTER(c_ubyte) namespace = create_string_buffer(namespace) ptr = lib.list_blob(namespace) data = ptr[:lib.size_of_listRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_listResponse()) if len(resp) < lib.size_of_listResponseFixed(): raise Blob2ListError("list response smaller than expected") errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) resp = resp + "\0" * (lib.size_of_listResponse() - len(resp)) self.unloadchifhandle(lib) return resp def finalize(self, key, namespace): """Finalize the blob :param key: The blob key to be finalized. :type key: str. :param namespace: The blob namespace to finalize the key in. :type namespace: str. """ lib = self.gethprestchifhandle() lib.finalize_blob.argtypes = [c_char_p, c_char_p] lib.finalize_blob.restype = POINTER(c_ubyte) name = create_string_buffer(key) namespace = create_string_buffer(namespace) ptr = lib.finalize_blob(name, namespace) data = ptr[:lib.size_of_finalizeRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_finalizeResponse()) if len(resp) > lib.size_of_finalizeResponse(): raise Blob2FinalizeError("finalize response smaller than expected") if len(resp) < lib.size_of_finalizeResponse(): raise Blob2FinalizeError("finalize response smaller than expected") errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return errorcode def rest_immediate(self, req_data, rqt_key="RisRequest", \ rsp_key="RisResponse", \ rsp_namespace="volatile"): """Read/write blob via immediate operation :param req_data: The blob data to be read/written. :type req_data: str. :param rqt_key: The blob key to be used for the request data. :type rqt_key: str. :param rsp_key: The blob key to be used for the response data. :type rsp_key: str. :param rsp_namespace: The blob namespace to retrieve the response from. :type rsp_namespace: str. """ rqt_key = ''.join(random.choice(string.ascii_letters + \ string.digits) for _ in range(10)) rsp_key = ''.join(random.choice(string.ascii_letters + \ string.digits) for _ in range(10)) lib = self.gethprestchifhandle() if len(req_data) < (lib.size_of_restImmediateRequest() + \ lib.max_write_size()): lib.rest_immediate.argtypes = [c_uint, c_char_p, c_char_p] lib.rest_immediate.restype = POINTER(c_ubyte) name = create_string_buffer(rsp_key) namespace = create_string_buffer(rsp_namespace) ptr = lib.rest_immediate(len(req_data), name, namespace) sendpacket = ptr[:lib.size_of_restImmediateRequest()] mode = False else: self.create(rqt_key, rsp_namespace) self.write(rqt_key, rsp_namespace, req_data) lib.rest_immediate_blobdesc.argtypes = [c_char_p, c_char_p, \ c_char_p] lib.rest_immediate_blobdesc.restype = POINTER(c_ubyte) name = create_string_buffer(rqt_key) namespace = create_string_buffer(rsp_namespace) rspname = create_string_buffer(rsp_key) ptr = lib.rest_immediate_blobdesc(name, rspname, namespace) sendpacket = ptr[:lib.size_of_restBlobRequest()] mode = True data = bytearray(sendpacket) if not mode: data.extend(req_data) resp = self._send_receive_raw(data, lib.size_of_restResponse()) errorcode = struct.unpack("<I", bytes(resp[8:12]))[0] if errorcode == BlobReturnCodes.NOTFOUND: raise BlobNotFoundError(rsp_key, rsp_namespace) recvmode = struct.unpack("<I", bytes(resp[12:16]))[0] fixdlen = lib.size_of_restResponseFixed() response = resp[fixdlen:struct.unpack("<I", bytes(resp[16:20]))[0] + \ fixdlen] tmpresponse = None if errorcode == BlobReturnCodes.SUCCESS and not mode: if recvmode == 0: tmpresponse = ''.join(map(chr, response)) elif errorcode == BlobReturnCodes.NOTMODIFIED and not mode: if recvmode == 0: tmpresponse = ''.join(map(chr, response)) elif errorcode == BlobReturnCodes.SUCCESS: if recvmode == 0: tmpresponse = ''.join(map(chr, response)) elif recvmode == 0: raise HpIloError(errorcode) self.unloadchifhandle(lib) if not tmpresponse and recvmode == 1: tmpresponse = self.read(rsp_key, rsp_namespace) try: self.delete(rsp_key, rsp_namespace) except Exception as excp: raise excp else: try: self.delete(rsp_key, rsp_namespace) except Blob2OverrideError as excp: pass except Exception as excp: raise excp return tmpresponse def mount_blackbox(self): """Operation to mount the blackbox partition""" lib = self.gethprestchifhandle() lib.blackbox_media_mount.argtypes = [] lib.blackbox_media_mount.restype = POINTER(c_ubyte) ptr = lib.blackbox_media_mount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_embeddedMediaResponse()) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def absaroka_media_mount(self): """Operation to mount the absaroka repo partition""" lib = self.gethprestchifhandle() lib.absaroka_media_mount.argtypes = [] lib.absaroka_media_mount.restype = POINTER(c_ubyte) ptr = lib.absaroka_media_mount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_embeddedMediaResponse()) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def gaius_media_mount(self): """Operation to mount the gaius media partition""" lib = self.gethprestchifhandle() lib.gaius_media_mount.argtypes = [] lib.gaius_media_mount.restype = POINTER(c_ubyte) ptr = lib.gaius_media_mount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_embeddedMediaResponse()) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def vid_media_mount(self): """Operation to mount the gaius media partition""" lib = self.gethprestchifhandle() lib.vid_media_mount.argtypes = [] lib.vid_media_mount.restype = POINTER(c_ubyte) ptr = lib.vid_media_mount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_embeddedMediaResponse()) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def mountflat(self): """Operation to mount the gaius media partition""" lib = self.gethprestchifhandle() lib.flat_media_mount.argtypes = [] lib.flat_media_mount.restype = POINTER(c_ubyte) ptr = lib.flat_media_mount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_embeddedMediaResponse()) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def media_unmount(self): """Operation to unmount the media partition""" lib = self.gethprestchifhandle() lib.media_unmount.argtypes = [] lib.media_unmount.restype = POINTER(c_ubyte) ptr = lib.media_unmount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_embeddedMediaResponse()) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def bb_media_unmount(self): """Operation to unmount the media partition""" lib = self.gethprestchifhandle() lib.bb_media_unmount.argtypes = [] lib.bb_media_unmount.restype = POINTER(c_ubyte) ptr = lib.bb_media_unmount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_embeddedMediaResponse()) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def vid_media_unmount(self): """Operation to unmount the media partition""" lib = self.gethprestchifhandle() lib.vid_media_unmount.argtypes = [] lib.vid_media_unmount.restype = POINTER(c_ubyte) ptr = lib.vid_media_unmount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_embeddedMediaResponse()) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def gaius_media_unmount(self): """Operation to unmount the media partition""" lib = self.gethprestchifhandle() lib.gaius_media_unmount.argtypes = [] lib.gaius_media_unmount.restype = POINTER(c_ubyte) ptr = lib.gaius_media_unmount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_embeddedMediaResponse()) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def absr_media_unmount(self): """Operation to unmount the media partition""" lib = self.gethprestchifhandle() lib.absaroka_media_unmount.argtypes = [] lib.absaroka_media_unmount.restype = POINTER(c_ubyte) ptr = lib.absaroka_media_unmount() data = ptr[:lib.size_of_embeddedMediaRequest()] data = bytearray(data) resp = self._send_receive_raw(data, lib.size_of_embeddedMediaResponse()) errorcode = resp[12] if not (errorcode == BlobReturnCodes.SUCCESS or\ errorcode == BlobReturnCodes.NOTMODIFIED): raise HpIloError(errorcode) self.unloadchifhandle(lib) return resp def _send_receive_raw(self, indata, datarecv=0): """Send and receive raw function for blob operations :param indata: The data to be sent to blob operation. :type indata: str. :param datarecv: The expected size of the blob operation response. :type datarecv: int. """ excp = None for _ in range(0, 3): # channel loop for iLO try: resp = self.channel.send_receive_raw(indata, 10, datarecv) return resp except Exception as excp: self.channel.close() self.channel = HpIlo() if excp: raise excp @staticmethod def gethprestchifhandle(): """Multi platform handle for chif hprest library""" excp = None libhandle = None libnames = ["ilorest_chif.dll", "hprest_chif.dll"] if os.name == \ 'nt' else ["ilorest_chif_dev.so", "hprest_chif_dev.so", \ "ilorest_chif.so", "hprest_chif.so"] for libname in libnames: try: libpath = BlobStore2.checkincurrdirectory(libname) libhandle = cdll.LoadLibrary(libpath) if libhandle: break except Exception as excp: pass if libhandle: BlobStore2.setglobalhprestchifrandnumber(libhandle) return libhandle raise ChifDllMissingError(excp) @staticmethod def setglobalhprestchifrandnumber(libbhndl): rndval = random.randint(1, 65535) libbhndl.updaterandval.argtypes = [c_ushort] libbhndl.updaterandval(rndval) @staticmethod def checkincurrdirectory(libname): """Check if the library is present in current directory.""" libpath = libname if os.path.isfile(os.path.join(os.path.split(sys.executable)[0], libpath)): libpath = os.path.join(os.path.split(sys.executable)[0], libpath) elif os.path.isfile(os.path.join(os.getcwd(), libpath)): libpath = os.path.join(os.getcwd(), libpath) return libpath @staticmethod def unloadchifhandle(lib): """Release a handle on the chif iLOrest library :param lib: The library handle provided by loading the chif library. :type lib: library handle. """ try: libhandle = lib._handle if os.name == 'nt': windll.kernel32.FreeLibrary(None, handle=libhandle) else: dlclose(libhandle) except Exception: pass