def unloadchifhandle(self, lib):
        """Release a handle on the chif hprest library

        :param lib: The library handle provided by loading the chif library.
        :type lib: library handle.
        """
        BlobStore2.unloadchifhandle(lib)
Example #2
0
    def __init__(self, base_url, default_prefix='/rest/v1', username=None, \
                            password=None, sessionkey=None, is_redfish=False, \
                            cache=False, proxy=None):

        """Initialize Blobstore2RestClient

        :param base_url: The url of the remote system
        :type base_url: str
        :param username: The username used for authentication
        :type username: str
        :param password: The password used for authentication
        :type password: str
        :param default_prefix: The default root point
        :type default_prefix: str
        :param biospassword: biospassword for base_url if needed
        :type biospassword: str
        :param sessionkey: sessionkey for the current login of base_url
        :type sessionkey: str
        :param is_redfish: flag for checking redfish
        :type is_redfish: bool

        """
        self.is_redfish = is_redfish
        self.creds = not cache

        try:
            if not cache:
                correctcreds = BlobStore2.initializecreds(username=username, \
                                                          password=password)
                bs2 = BlobStore2()
                if not correctcreds:
                    security_state = int(bs2.get_security_state())
                    raise SecurityStateError(security_state)
        except Blob2SecurityError:
            raise InvalidCredentialsError(0)
        except HpIloChifPacketExchangeError as excp:
            LOGGER.info("Exception: %s", str(excp))
            raise ChifDriverMissingOrNotFound()
        except Exception as excp:
            if excp.message == 'chif':
                raise ChifDriverMissingOrNotFound()
            else:
                raise

        super(Blobstore2RestClient, self).__init__(base_url, \
                        username=username, password=password, \
                        default_prefix=default_prefix, sessionkey=sessionkey,\
                        cache=cache, is_redfish=is_redfish)
    def create_new_chif_for_upload(self, user, passwrd):

        dll = BlobStore2.gethprestchifhandle()
        dll.ChifInitialize(None)
        # Enable Security Flag in Chif
        dll.ChifEnableSecurity()
        fhandle = c_void_p()
        dll.ChifCreate.argtypes = [c_void_p]
        dll.ChifCreate.restype = c_uint32
        status = dll.ChifCreate(byref(fhandle))
        if status != BlobReturnCodes.SUCCESS:
            raise HpIloInitialError(
                "Error %s occurred while trying to create a channel." % status)
        dll.initiate_credentials.argtypes = [c_char_p, c_char_p]
        dll.initiate_credentials.restype = POINTER(c_ubyte)
        usernew = create_string_buffer(user.encode('utf-8'))
        passnew = create_string_buffer(passwrd.encode('utf-8'))
        dll.initiate_credentials(usernew, passnew)
        status = dll.ChifPing(fhandle)
        if status != BlobReturnCodes.SUCCESS:
            raise HpIloInitialError(
                "Error %s occurred while trying to create a channel." % status)
        dll.ChifSetRecvTimeout(fhandle, 60000)
        credreturn = dll.ChifVerifyCredentials()
        if not credreturn == BlobReturnCodes.SUCCESS:
            if credreturn == BlobReturnCodes.CHIFERR_AccessDenied:
                raise Blob2SecurityError()
            else:
                raise HpIloInitialError("Error %s occurred while trying " \
                                        "to open a channel to iLO" % credreturn)
        return dll, fhandle
    def preparefwpkg(self, pkgfile):
        """ Prepare fwpkg file for flashing

        :param pkgfile: Location of the .fwpkg file
        :type pkgfile: string.
        :returns: returns the files needed to flash, directory they are located
                                                            in, and type of file.
        :rtype: string, string, string
        """
        files = []
        imagefiles = []
        payloaddata = None
        tempdir = tempfile.mkdtemp()

        try:
            zfile = zipfile.ZipFile(pkgfile)
            zfile.extractall(tempdir)
            zfile.close()
        except Exception as excp:
            raise InvalidFileInputError("Unable to unpack file. " + str(excp))

        files = os.listdir(tempdir)

        if 'payload.json' in files:
            with open(os.path.join(tempdir, 'payload.json'), "r") as pfile:
                data = pfile.read()
            payloaddata = json.loads(data)
        else:
            raise InvalidFileInputError(
                "Unable to find payload.json in fwpkg file.")

        comptype = _get_comp_type(payloaddata)

        if comptype == 'C':
            imagefiles = [self.type_c_change(tempdir, pkgfile)]
        else:
            results = self._rdmc.app.getprops(selector="UpdateService.", \
                                                                props=['Oem/Hpe/Capabilities'])

            for device in payloaddata['Devices']['Device']:
                for firmwareimage in device['FirmwareImages']:
                    if firmwareimage['FileName'] not in imagefiles:
                        imagefiles.append(firmwareimage['FileName'])

        if comptype in ['A','B'] and results and 'UpdateFWPKG' in results[0]['Oem']['Hpe']\
                                                                                ['Capabilities']:
            dll = BlobStore2.gethprestchifhandle()
            dll.isFwpkg20.argtypes = [c_char_p, c_int]
            dll.isFwpkg20.restype = c_bool

            with open(pkgfile, 'rb') as fwpkgfile:
                fwpkgdata = fwpkgfile.read()

            fwpkg_buffer = ctypes.create_string_buffer(fwpkgdata)
            if dll.isFwpkg20(fwpkg_buffer, 2048):
                imagefiles = [pkgfile]
                tempdir = ''

        return imagefiles, tempdir, comptype
 def gethprestchifhandle(self):
     """ Load the chif hprest library
     """
     try:
         lib = BlobStore2.gethprestchifhandle()
     except Exception as excp:
         lib = None
     return lib
Example #6
0
    def updatecredentials(self):
        """update credentials for high security if needed
        """
        if not self.creds:
            user = self._RestClientBase__username
            password = self._RestClientBase__password
            try:
                correctcreds = BlobStore2.initializecreds(username=user, \
                                                          password=password)
                if not correctcreds:
                    security_state = int(BlobStore2().get_security_state())
                    raise SecurityStateError(security_state)
            except Blob2SecurityError:
                raise InvalidCredentialsError(0)
            except Exception:
                raise

            self.creds = True
Example #7
0
def get_client_instance(base_url=None, username=None, password=None, \
                                default_prefix='/rest/v1', biospassword=None, \
                                sessionkey=None, is_redfish=False, cache=False, \
                                proxy=None):
    """Create and return appropriate RESTful/REDFISH client instance.
    Instantiates appropriate Rest/Redfish object based on existing
    configuration. Use this to retrieve a pre-configured Rest object

    :param base_url: rest host or ip address.
    :type base_url: str.
    :param username: username required to login to server
    :type: str
    :param password: password credentials required to login
    :type password: str
    :param default_prefix: default root to extract tree
    :type default_prefix: str
    :param biospassword: BIOS password for the server if set
    :type biospassword: str
    :param sessionkey: session key credential for current login
    :type sessionkey: str
    :param is_redfish: If True, a Redfish specific header (OData)
    will be added to every request
    :type is_redfish: boolean
    :returns: a client object. Either HTTP or Blobstore.

    """
    if not base_url or base_url.startswith('blobstore://'):
        if platform.system() == 'Windows':
            lib = BlobStore2.gethprestchifhandle()
            BlobStore2.unloadchifhandle(lib)
        else:
            if not os.path.isdir('/dev/hpilo') and \
               not os.path.exists('/dev/char/vmkdriver/hpilo-d0ccb0'):
                raise ChifDriverMissingOrNotFound()

        return Blobstore2RestClient(base_url=base_url, \
                            default_prefix=default_prefix, username=username, \
                            password=password, sessionkey=sessionkey, \
                            is_redfish=is_redfish, cache=cache, proxy=proxy)
    else:
        return HttpClient(base_url=base_url, username=username, \
                          password=password, default_prefix=default_prefix, \
                          biospassword=biospassword, sessionkey=sessionkey, \
                          is_redfish=is_redfish, cache=cache, proxy=proxy)
 def _init_connection(self, **kwargs):
     """Initiate blobstore connection"""
     # mixed security modes require a password at all times
     username = kwargs.pop('username', 'nousername')
     password = kwargs.pop('password', 'nopassword')
     try:
         correctcreds = BlobStore2.initializecreds(username=username,
                                                   password=password)
         bs2 = BlobStore2()
         if not correctcreds:
             security_state = int(bs2.get_security_state())
             raise SecurityStateError(security_state)
     except Blob2SecurityError:
         raise InvalidCredentialsError(0)
     except HpIloChifPacketExchangeError as excp:
         LOGGER.info("Exception: %s", str(excp))
         raise ChifDriverMissingOrNotFound()
     except Exception as excp:
         if str(excp) == 'chif':
             raise ChifDriverMissingOrNotFound()
         else:
             raise
     else:
         self._conn = bs2
    def getpaths(self):
        """ Get paths for ipprofiles command """
        if not all(
                iter([
                    self.path, self.ipjobs, self.running_jobs, self.hvt_output
                ])):
            dll = BlobStore2.gethprestchifhandle()

            profiles_path = create_string_buffer(50)
            jobs_path = create_string_buffer(50)
            running_jobs_path = create_string_buffer(50)
            hvt_output_path = create_string_buffer(50)

            dll.get_ip_profiles(profiles_path)
            dll.get_ip_jobs(jobs_path)
            dll.get_running_jobs(running_jobs_path)
            dll.get_hvt_output(hvt_output_path)

            self.path = profiles_path.value
            self.ipjobs = jobs_path.value
            self.running_jobs = running_jobs_path.value
            self.hvt_output = hvt_output_path.value
    def uploadlocally(self, filelist, options=None):
        """Upload component locally

        :param filelist: List of files to upload.
        :type filelist: list.
        :param options: command line options
        :type options: list.
        """
        new_chif_needed = False
        upload_failed = False
        if not options.update_target:
            options.upload_srs = False

        if options.update_srs:
            if options.user and options.password:
                new_chif_needed = True
            else:
                self.rdmc.ui.error("ERROR: --update_srs option needs to be passed with "\
                                   "--username and --password options, upload failed\n")
                return ReturnCodes.FAILED_TO_UPLOAD_COMPONENT
        try:
            dll = self.rdmc.app.current_client.connection._conn.channel.dll
            multiupload = False

            if new_chif_needed:
                # Backup old chif channel
                dll_bk = dll
                dll = None
                user = options.user
                passwrd = options.password
                dll, fhandle = self.create_new_chif_for_upload(user, passwrd)

            dll.uploadComponent.argtypes = [
                c_char_p, c_char_p, c_char_p, c_uint32
            ]
            dll.uploadComponent.restype = c_int

            for item in filelist:

                ilo_upload_filename = item[0]
                componentpath = item[1]
                compsigpath = item[2]

                if not compsigpath:
                    compsigpath = self.findcompsig(componentpath)

                _, filename = os.path.split(componentpath)

                # 0x00000001  // FUM_WRITE_NAND
                # 0x00000002  // FUM_USE_NAND
                # 0x00000004  // FUM_NO_FLASH
                # 0x00000008  // FUM_FORCE
                # 0x00000010  // FUM_SIDECAR
                # 0x00000020  // FUM_APPEND
                # 0x40  // FUM_UPDATE_RECOVERY
                # 0x00000080   //FUM_RECOVERY
                # 0x00000100 // FUM_TASK
                # 0x00000200  //FUM_RECO_PRIV

                if not compsigpath and options.update_target:
                    # Just update the firmware
                    if options.update_srs:
                        dispatchflag = ctypes.c_uint32(0x00000000 | 0x40)
                    else:
                        dispatchflag = ctypes.c_uint32(0x00000000)
                elif not compsigpath and not options.update_target and \
                                                    options.update_repository:
                    # uploading a secuare flash binary image onto the NAND
                    if options.update_srs:
                        dispatchflag = ctypes.c_uint32(0x00000001 | 0x00000004
                                                       | 0x40)
                    else:
                        dispatchflag = ctypes.c_uint32(0x00000001 | 0x00000004)
                else:
                    # Uploading a component with a side car file.
                    if options.update_srs:
                        dispatchflag = ctypes.c_uint32(0x00000001 | 0x00000004
                                                       | 0x00000010 | 0x40)
                    else:
                        dispatchflag = ctypes.c_uint32(0x00000001 | 0x00000004
                                                       | 0x00000010)

                if multiupload:
                    # For second upload to append if the component is > 32MB in size
                    if options.update_srs:
                        dispatchflag = ctypes.c_uint32(0x00000001 | 0x00000004 | \
                                                       0x00000010 | 0x00000020 | 0x40)
                    else:
                        dispatchflag = ctypes.c_uint32(0x00000001 | 0x00000004 | \
                                                       0x00000010 | 0x00000020)

                self.rdmc.ui.printer("Uploading component " + filename + "\n")

                ret = dll.uploadComponent(\
                  ctypes.create_string_buffer(compsigpath.encode('utf-8')),
                  ctypes.create_string_buffer(componentpath.encode('utf-8')),
                  ctypes.create_string_buffer(ilo_upload_filename.encode('utf-8')), dispatchflag)

                upload_failed = False
                if ret != 0:
                    self.rdmc.ui.error("Component " + filename +
                                       " upload failed\n")
                    upload_failed = True
                else:
                    self.rdmc.ui.printer("Component " + filename +
                                         " uploaded successfully\n")

                multiupload = True

                if new_chif_needed:
                    dll.ChifTerminate()
                    dll.ChifClose(fhandle)
                    fhandle = None
                    BlobStore2.unloadchifhandle(dll)
                    # Restore old chif channel
                    dll = dll_bk

        except Exception as excep:
            raise excep

        if upload_failed:
            return ReturnCodes.FAILED_TO_UPLOAD_COMPONENT
        else:
            return ReturnCodes.SUCCESS
Example #11
0
    def _rest_request(self, path='', method="GET", args=None, body=None,
                      headers=None, optionalpassword=None, providerheader=None):
        """Rest request for blob store client

        :param path: path within tree
        :type path: str
        :param method: method to be implemented
        :type method: str
        :param args: the arguments for method
        :type args: dict
        :param body: body payload for the rest call
        :type body: dict
        :param headers: provide additional headers
        :type headers: dict
        :param optionalpassword: provide password for authentication
        :type optionalpassword: str
        :param provideheader: provider id for the header
        :type providerheader: str
        :return: returns a RestResponse object

        """
        self.updatecredentials()
        headers = self._get_req_headers(headers, providerheader, \
                                                            optionalpassword)

        reqpath = path.replace('//', '/')

        oribody = body
        if body is not None:
            if isinstance(body, (dict, list)):
                headers['Content-Type'] = 'application/json'
                body = json.dumps(body)
            else:
                headers['Content-Type'] = 'application/x-www-form-urlencoded'
                body = urlencode(body)

            if method == 'PUT':
                resp = self._rest_request(path=path)

                try:
                    if resp.getheader('content-encoding') == 'gzip':
                        buf = StringIO()
                        gfile = gzip.GzipFile(mode='wb', fileobj=buf)

                        try:
                            gfile.write(str(body))
                        finally:
                            gfile.close()

                        compresseddata = buf.getvalue()
                        if compresseddata:
                            data = bytearray()
                            data.extend(memoryview(compresseddata))
                            body = data
                except BaseException as excp:
                    LOGGER.error('Error occur while compressing body: %s', excp)
                    raise

            headers['Content-Length'] = len(body)

        if args:
            if method == 'GET':
                reqpath += '?' + urlencode(args)
            elif method == 'PUT' or method == 'POST' or method == 'PATCH':
                headers['Content-Type'] = 'application/x-www-form-urlencoded'
                body = urlencode(args)

        str1 = '{} {} {}\r\n'.format(method, reqpath, \
                                            Blobstore2RestClient._http_vsn_str)
        str1 += 'Host: \r\n'
        str1 += 'Accept-Encoding: identity\r\n'
        for header, value in headers.items():
            str1 += '{}: {}\r\n'.format(header, value)

        str1 += '\r\n'

        if body and len(body) > 0:
            if isinstance(body, bytearray):
                str1 = str1.encode("ASCII") + body
            else:
                str1 += body

        bs2 = BlobStore2()

        if not isinstance(str1, bytearray):
            str1 = str1.encode("ASCII")

        if LOGGER.isEnabledFor(logging.DEBUG):
            try:
                logbody = None
                if body:
                    if body[0] == '{':
                        logbody = body
                    else:
                        raise
                if method in ['POST', 'PATCH']:
                    debugjson = json.loads(body)
                    if 'Password' in debugjson.keys():
                        debugjson['Password'] = '******'
                    if 'OldPassword' in debugjson.keys():
                        debugjson['OldPassword'] = '******'
                    if 'NewPassword' in debugjson.keys():
                        debugjson['NewPassword'] = '******'
                    logbody = json.dumps(debugjson)

                LOGGER.debug('Blobstore REQUEST: %s\n\tPATH: %s\n\tHEADERS: '\
                             '%s\n\tBODY: %s', method, str(headers), path, logbody)
            except:
                LOGGER.debug('Blobstore REQUEST: %s\n\tPATH: %s\n\tHEADERS: '\
                             '%s\n\tBODY: %s', method, str(headers), path, 'binary body')

        inittime = time.time()

        for idx in range(5):
            try:
                resp_txt = bs2.rest_immediate(str1)
                break
            except Blob2OverrideError as excp:
                if idx == 4:
                    raise Blob2OverrideError(2)
                else:
                    continue

        endtime = time.time()

        bs2.channel.close()

        LOGGER.info("iLO Response Time to %s: %s secs.", path, str(endtime-inittime))
        #Dummy response to support a bad host response
        if len(resp_txt) == 0:
            resp_txt = "HTTP/1.1 500 Not Found\r\nAllow: " \
            "GET\r\nCache-Control: no-cache\r\nContent-length: " \
            "0\r\nContent-type: text/html\r\nDate: Tues, 1 Apr 2025 " \
            "00:00:01 GMT\r\nServer: " \
            "HP-iLO-Server/1.30\r\nX_HP-CHRP-Service-Version: 1.0.3\r\n\r\n\r\n"

        restreq = RestRequest(path, method, data=body, url=self.base_url)
        rest_response = RisRestResponse(restreq, resp_txt)

        if rest_response.status in range(300, 399) and \
                                                    rest_response.status != 304:
            newloc = rest_response.getheader("location")
            newurl = urlparse(newloc)

            rest_response = self._rest_request(newurl.path, method, args, \
                               oribody, headers, optionalpassword, \
                               providerheader)

        try:
            if rest_response.getheader('content-encoding') == 'gzip':
                if hasattr(gzip, "decompress"):
                    rest_response.read = gzip.decompress(rest_response.ori)
                else:
                    compressedfile = StringIO(rest_response.ori)
                    decompressedfile = gzip.GzipFile(fileobj=compressedfile)
                    rest_response.read = decompressedfile.read()
        except Exception:
            pass
        if LOGGER.isEnabledFor(logging.DEBUG):
            headerstr = ''
            headerget = rest_response.getheaders()
            for header in headerget:
                headerstr += '\t' + header + ': ' + headerget[header] + '\n'
            try:
                LOGGER.debug('Blobstore RESPONSE for %s:\nCode: %s\nHeaders:'\
                            '\n%s\nBody of %s: %s', rest_response.request.path,\
                            str(rest_response._http_response.status)+ ' ' + \
                            rest_response._http_response.reason, \
                            headerstr, rest_response.request.path, \
                            rest_response.read)
            except:
                LOGGER.debug('Blobstore RESPONSE for %s:\nCode:%s', \
                             rest_response.request.path, rest_response)
        return rest_response
Example #12
0
    def _rest_request(self, path='', method="GET", args=None, body=None,
                      headers=None, optionalpassword=None, providerheader=None):
        """Rest request for blob store client

        :param path: path within tree
        :type path: str
        :param method: method to be implemented
        :type method: str
        :param args: the arguments for method
        :type args: dict
        :param body: body payload for the rest call
        :type body: dict
        :param headers: provide additional headers
        :type headers: dict
        :param optionalpassword: provide password for authentication
        :type optionalpassword: str
        :param provideheader: provider id for the header
        :type providerheader: str
        :return: returns a RestResponse object

        """
        headers = self._get_req_headers(headers, providerheader, \
                                                            optionalpassword)

        reqpath = path.replace('//', '/')

        oribody = body
        if body is not None:
            if isinstance(body, dict) or isinstance(body, list):
                headers['Content-Type'] = u'application/json'
                body = json.dumps(body)
            else:
                headers['Content-Type'] = u'application/x-www-form-urlencoded'
                body = urllib.urlencode(body)

            if method == 'PUT':
                resp = self._rest_request(path=path)

                try:
                    if resp.getheader('content-encoding') == 'gzip':
                        buf = StringIO()
                        gfile = gzip.GzipFile(mode='wb', fileobj=buf)

                        try:
                            gfile.write(str(body))
                        finally:
                            gfile.close()

                        compresseddata = buf.getvalue()
                        if compresseddata:
                            data = bytearray()
                            data.extend(buffer(compresseddata))
                            body = data
                except BaseException as excp:
                    LOGGER.error('Error occur while compressing body: %s', excp)
                    raise

            headers['Content-Length'] = len(body)

        if args:
            if method == 'GET':
                reqpath += '?' + urllib.urlencode(args)
            elif method == 'PUT' or method == 'POST' or method == 'PATCH':
                headers['Content-Type'] = u'application/x-www-form-urlencoded'
                body = urllib.urlencode(args)

        str1 = '%s %s %s\r\n' % (method, reqpath, \
                                            Blobstore2RestClient._http_vsn_str)

        str1 += 'Host: \r\n'
        str1 += 'Accept-Encoding: identity\r\n'
        for header, value in headers.iteritems():
            str1 += '%s: %s\r\n' % (header, value)

        str1 += '\r\n'

        if body and len(body) > 0:
            if isinstance(body, bytearray):
                str1 = str1.encode("ASCII") + body
            else:
                str1 += body

        bs2 = BlobStore2()
        if not isinstance(str1, bytearray):
            str1 = str1.encode("ASCII")
        if logging.getLogger().isEnabledFor(logging.DEBUG):
            try:
                LOGGER.debug('Blobstore REQUEST: %s\n\tPATH: %s\n\tBODY: %s'% \
                         (method, path, body))
            except:
                LOGGER.debug('Blobstore REQUEST: %s\n\tPATH: %s\n\tBODY: %s'% \
                         (method, path, 'binary body'))                

        inittime = time.clock()
        resp_txt = bs2.rest_immediate(str1)
        endtime = time.clock()

        bs2.channel.close()

        LOGGER.info("iLO Response Time to %s: %s secs."% \
                                                (path, str(endtime-inittime)))
        #Dummy response to support a bad host response
        if len(resp_txt) == 0:
            resp_txt = "HTTP/1.1 500 Not Found\r\nAllow: " \
            "GET\r\nCache-Control: no-cache\r\nContent-length: " \
            "0\r\nContent-type: text/html\r\nDate: Tues, 1 Apr 2025 " \
            "00:00:01 GMT\r\nServer: " \
            "HP-iLO-Server/1.30\r\nX_HP-CHRP-Service-Version: 1.0.3\r\n\r\n\r\n"

        restreq = RestRequest(reqpath, method=method, body=body)
        rest_response = RisRestResponse(restreq, resp_txt)

        if rest_response.status in range(300, 399) and \
                                                    rest_response.status != 304:
            newloc = rest_response.getheader("location")
            newurl = urlparse2.urlparse(newloc)

            rest_response = self._rest_request(newurl.path, method, args, \
                               oribody, headers, optionalpassword, providerheader)

        try:
            if rest_response.getheader('content-encoding') == 'gzip':
                compressedfile = StringIO(rest_response.text)
                decompressedfile = gzip.GzipFile(fileobj=compressedfile)
                rest_response.text = decompressedfile.read()
        except StandardError:
            pass
        if logging.getLogger().isEnabledFor(logging.DEBUG):
            headerstr = ''
            for header in rest_response._http_response.msg.headers:
                headerstr += '\t' + header.rstrip() + '\n'
            try:
                LOGGER.debug('Blobstore RESPONSE for %s:\nCode: %s\nHeaders:\n%s'\
                         '\nBody of %s: %s'%\
                         (rest_response.request.path,\
                        str(rest_response._http_response.status)+ ' ' + \
                        rest_response._http_response.reason, \
                        headerstr, rest_response.request.path, rest_response.read))
            except:
                LOGGER.debug('Blobstore RESPONSE for %s:\nCode:%s'% \
                             (rest_response.request.path, rest_response))
        return rest_response