Пример #1
0
    def _wait_session(self, session_id, timeout=1800):
        session_expiration = time.time() + timeout

        while True:
            resp = elcm.elcm_session_get_status(self.irmc_info, session_id)

            status = resp['Session']['Status']
            if status == 'running' or status == 'activated':
                # Sleep a bit
                time.sleep(5)
            elif status == 'terminated regularly':
                return {}
            else:
                # Error occurred, get session log to see what happened
                try:
                    session_log = elcm.elcm_session_get_log(
                        irmc_info=self.irmc_info, session_id=session_id)
                except scci.SCCIClientError as e:
                    raise scci.SCCIClientError(
                        ('Operation Failed. Session %(session_id)s state is '
                         '%(session_state)s. Session log collection failed: '
                         '%(reason)s' % {
                             'session_id': session_id,
                             'session_state': resp['Session']['Status'],
                             'reason': e
                         }))

                raise scci.SCCIClientError(
                    ('Operation failed. Session %(session_id)s state is '
                     '%(session_state)s. Session log is: "%(session_log)s".' %
                     {
                         'session_id': session_id,
                         'session_state': resp['Session']['Status'],
                         'session_log': json.dumps(session_log)
                     }))

            # Check for timeout
            if time.time() > session_expiration:
                # Timeout occurred, get session log to see what happened
                try:
                    session_log = elcm.elcm_session_get_log(
                        irmc_info=self.irmc_info, session_id=session_id)
                except scci.SCCIClientError as e:
                    raise elcm.ELCMSessionTimeout(
                        'Operation timed out. Session %(session_id)s has not '
                        'finished in %(timeout)d seconds. Session log '
                        'collection failed: %(reason)s' % {
                            'session_id': session_id,
                            'timeout': timeout,
                            'reason': e
                        })

                raise elcm.ELCMSessionTimeout(
                    'Operation timed out. Session %(session_id)s has not '
                    'finished in %(timeout)d seconds. Session log is: '
                    '"%(session_log)s.' % {
                        'session_id': session_id,
                        'timeout': timeout,
                        'session_log': json.dumps(session_log)
                    })
Пример #2
0
def elcm_session_delete(irmc_info, session_id, terminate=False):
    """send an eLCM request to remove a session from the session list

    :param irmc_info: node info
    :param session_id: session id
    :param terminate: a running session must be terminated before removing
    :raises: ELCMSessionNotFound if the session does not exist
    :raises: SCCIClientError if SCCI failed
    """
    # Terminate the session first if needs to
    if terminate:
        # Get session status to check
        session = elcm_session_get_status(irmc_info, session_id)
        status = session['Session']['Status']

        # Terminate session if it is activated or running
        if status == 'running' or status == 'activated':
            elcm_session_terminate(irmc_info, session_id)

    # Send DELETE request to the server
    resp = elcm_request(irmc_info,
                        method='DELETE',
                        path='/sessionInformation/%s/remove' % session_id)

    if resp.status_code == 200:
        return
    elif resp.status_code == 404:
        raise ELCMSessionNotFound('Session "%s" does not exist' % session_id)
    else:
        raise scci.SCCIClientError(
            ('Failed to remove session '
             '"%(session)s" with error code %(error)s' % {
                 'session': session_id,
                 'error': resp.status_code
             }))
Пример #3
0
def elcm_session_get_log(irmc_info, session_id):
    """send an eLCM request to get session log

    :param irmc_info: node info
    :param session_id: session id
    :returns: dict object of session log if succeed
        {
          'Session':
          {
            'Id': id
            ...
          }
        }
    :raises: ELCMSessionNotFound if the session does not exist
    :raises: SCCIClientError if SCCI failed
    """
    # Send GET request to the server
    resp = elcm_request(irmc_info,
                        method='GET',
                        path='/sessionInformation/%s/log' % session_id)

    if resp.status_code == 200:
        return _parse_elcm_response_body_as_json(resp)
    elif resp.status_code == 404:
        raise ELCMSessionNotFound('Session "%s" does not exist' % session_id)
    else:
        raise scci.SCCIClientError(
            ('Failed to get log of session '
             '"%(session)s" with error code %(error)s' % {
                 'session': session_id,
                 'error': resp.status_code
             }))
Пример #4
0
def elcm_session_list(irmc_info):
    """send an eLCM request to list all sessions

    :param irmc_info: node info
    :returns: dict object of sessions if succeed
        {
          'SessionList':
          {
            'Contains':
            [
              { 'Id': id1, 'Name': name1 },
              { 'Id': id2, 'Name': name2 },
              { 'Id': idN, 'Name': nameN },
            ]
          }
        }
    :raises: SCCIClientError if SCCI failed
    """
    # Send GET request to the server
    resp = elcm_request(irmc_info, method='GET', path='/sessionInformation/')

    if resp.status_code == 200:
        return _parse_elcm_response_body_as_json(resp)
    else:
        raise scci.SCCIClientError(('Failed to list sessions with '
                                    'error code %s' % resp.status_code))
Пример #5
0
def elcm_profile_delete(irmc_info, profile_name):
    """send an eLCM request to delete a profile

    :param irmc_info: node info
    :param profile_name: name of profile
    :raises: ELCMProfileNotFound if the profile does not exist
    :raises: SCCIClientError if SCCI failed
    """
    # Send DELETE request to the server
    resp = elcm_request(irmc_info,
                        method='DELETE',
                        path=URL_PATH_PROFILE_MGMT + profile_name)

    if resp.status_code == 200:
        # Profile deleted
        return
    elif resp.status_code == 404:
        # Profile not found
        raise ELCMProfileNotFound('Profile "%s" not found '
                                  'in the profile store.' % profile_name)
    else:
        raise scci.SCCIClientError(('Failed to delete profile "%(profile)s" '
                                    'with error code %(error)s' % {
                                        'profile': profile_name,
                                        'error': resp.status_code
                                    }))
Пример #6
0
def elcm_profile_get(irmc_info, profile_name):
    """send an eLCM request to get profile data

    :param irmc_info: node info
    :param profile_name: name of profile
    :returns: dict object of profile data if succeed
    :raises: ELCMProfileNotFound if profile does not exist
    :raises: SCCIClientError if SCCI failed
    """
    # Send GET request to the server
    resp = elcm_request(irmc_info,
                        method='GET',
                        path=URL_PATH_PROFILE_MGMT + profile_name)

    if resp.status_code == 200:
        return _parse_elcm_response_body_as_json(resp)
    elif resp.status_code == 404:
        raise ELCMProfileNotFound('Profile "%s" not found '
                                  'in the profile store.' % profile_name)
    else:
        raise scci.SCCIClientError(('Failed to get profile "%(profile)s" with '
                                    'error code %(error)s' % {
                                        'profile': profile_name,
                                        'error': resp.status_code
                                    }))
Пример #7
0
def elcm_profile_list(irmc_info):
    """send an eLCM request to list all profiles

    :param irmc_info: node info
    :returns: dict object of profiles if succeed
        {
          'Links':
          {
            'profileStore':
            [
              { '@odata.id': id1 },
              { '@odata.id': id2 },
              { '@odata.id': idN },
            ]
          }
        }
    :raises: SCCIClientError if SCCI failed
    """
    # Send GET request to the server
    resp = elcm_request(irmc_info, method='GET', path=URL_PATH_PROFILE_MGMT)

    if resp.status_code == 200:
        return _parse_elcm_response_body_as_json(resp)
    else:
        raise scci.SCCIClientError(('Failed to list profiles with '
                                    'error code %s' % resp.status_code))
Пример #8
0
def elcm_profile_set(irmc_info, input_data):
    """send an eLCM request to set param values

    To apply param values, a new session is spawned with status 'running'.
    When values are applied or error, the session ends.

    :param irmc_info: node info
    :param input_data: param values to apply, eg.
        {
          'Server':
          {
            'SystemConfig':
            {
              'BiosConfig':
              {
                '@Processing': 'execute',
                -- config data --
              }
            }
          }
        }
    :returns: dict object of session info if succeed
        {
          'Session':
          {
            'Id': id
            'Status': 'activated'
            ...
          }
        }
    :raises: SCCIClientError if SCCI failed
    """
    # Prepare the data to apply
    if isinstance(input_data, dict):
        data = jsonutils.dumps(input_data)
    else:
        data = input_data

    # Send POST request to the server
    # NOTE: This task may take time, so set a timeout
    _irmc_info = dict(irmc_info)
    _irmc_info['irmc_client_timeout'] = PROFILE_SET_TIMEOUT

    content_type = 'application/x-www-form-urlencoded'
    if input_data['Server'].get('HWConfigurationIrmc'):
        content_type = 'application/json'
    resp = elcm_request(_irmc_info,
                        method='POST',
                        path=URL_PATH_PROFILE_MGMT + 'set',
                        headers={'Content-type': content_type},
                        data=data)

    if resp.status_code == 202:
        return _parse_elcm_response_body_as_json(resp)
    else:
        raise scci.SCCIClientError(('Failed to apply param values with '
                                    'error code %(error)s' % {
                                        'error': resp.status_code
                                    }))
Пример #9
0
def elcm_session_terminate(irmc_info, session_id):
    """send an eLCM request to terminate a session

    :param irmc_info: node info
    :param session_id: session id
    :raises: ELCMSessionNotFound if the session does not exist
    :raises: SCCIClientError if SCCI failed
    """
    # Send DELETE request to the server
    resp = elcm_request(irmc_info,
                        method='DELETE',
                        path='/sessionInformation/%s/terminate' % session_id)

    if resp.status_code == 200:
        return
    elif resp.status_code == 404:
        raise ELCMSessionNotFound('Session "%s" does not exist' % session_id)
    else:
        raise scci.SCCIClientError(('Failed to terminate session '
                                    '"%(session)s" with error code %(error)s' %
                                    {'session': session_id,
                                     'error': resp.status_code}))
Пример #10
0
def elcm_profile_create(irmc_info, param_path):
    """send an eLCM request to create profile

    To create a profile, a new session is spawned with status 'running'.
    When profile is created completely, the session ends.

    :param irmc_info: node info
    :param param_path: path of profile
    :returns: dict object of session info if succeed
        {
          'Session':
          {
            'Id': id
            'Status': 'activated'
            ...
          }
        }
    :raises: SCCIClientError if SCCI failed
    """
    # Send POST request to the server
    # NOTE: This task may take time, so set a timeout
    _irmc_info = dict(irmc_info)
    _irmc_info['irmc_client_timeout'] = PROFILE_CREATE_TIMEOUT

    resp = elcm_request(_irmc_info,
                        method='POST',
                        path=URL_PATH_PROFILE_MGMT + 'get',
                        params={'PARAM_PATH': param_path})

    if resp.status_code == 202:
        return _parse_elcm_response_body_as_json(resp)
    else:
        raise scci.SCCIClientError(('Failed to create profile for path '
                                    '"%(param_path)s" with error code '
                                    '%(error)s' % {
                                        'param_path': param_path,
                                        'error': resp.status_code
                                    }))
Пример #11
0
def _process_session_data(irmc_info,
                          operation,
                          session_id,
                          session_timeout=BIOS_CONFIG_SESSION_TIMEOUT):
    """process session for Bios config backup/restore or RAID config operation

    :param irmc_info: node info
    :param operation: one of 'BACKUP_BIOS', 'RESTORE_BIOS' or 'CONFIG_RAID'
    :param session_id: session id
    :param session_timeout: session timeout
    :return: a dict with following values:
        {
            'bios_config': <data in case of BACKUP/RESTORE_BIOS operation>,
            'warning': <warning message if there is>
        }
    or
        {
            'raid_config': <data of raid adapter profile>,
            'warning': <warning message if there is>
        }
    """
    session_expiration = time.time() + session_timeout

    while time.time() < session_expiration:
        # Get session status to check
        session = elcm_session_get_status(irmc_info=irmc_info,
                                          session_id=session_id)

        status = session['Session']['Status']
        if status == 'running' or status == 'activated':
            # Sleep a bit
            time.sleep(5)
        elif status == 'terminated regularly':
            result = {}

            if operation == 'BACKUP_BIOS':
                # Bios profile is created, get the data now
                result['bios_config'] = elcm_profile_get(
                    irmc_info=irmc_info, profile_name=PROFILE_BIOS_CONFIG)
            elif operation == 'RESTORE_BIOS':
                # Bios config applied successfully
                pass
            elif operation == 'CONFIG_RAID':
                # Getting raid config
                result['raid_config'] = elcm_profile_get(
                    irmc_info, PROFILE_RAID_CONFIG)

            # Cleanup operation by deleting related session and profile.
            # In case of error, report it as warning instead of error.
            try:
                elcm_session_delete(irmc_info=irmc_info,
                                    session_id=session_id,
                                    terminate=True)
                if operation == 'CONFIG_RAID':
                    return result

                elcm_profile_delete(irmc_info=irmc_info,
                                    profile_name=PROFILE_BIOS_CONFIG)

            except scci.SCCIError as e:
                result['warning'] = e

            return result
        else:
            # Error occurred, get session log to see what happened
            session_log = elcm_session_get_log(irmc_info=irmc_info,
                                               session_id=session_id)

            raise scci.SCCIClientError(
                ('Failed to %(operation)s config. '
                 'Session log is "%(session_log)s".' % {
                     'operation': operation,
                     'session_log': jsonutils.dumps(session_log)
                 }))

    else:
        raise ELCMSessionTimeout(('Failed to %(operation)s config. '
                                  'Session %(session_id)s log is timeout.' % {
                                      'operation': operation,
                                      'session_id': session_id
                                  }))
Пример #12
0
def elcm_request(irmc_info, method, path, **kwargs):
    """send an eLCM request to the server

    :param irmc_info: dict of iRMC params to access the server node
        {
          'irmc_address': host,
          'irmc_username': user_id,
          'irmc_password': password,
          'irmc_port': 80 or 443, default is 443,
          'irmc_auth_method': 'basic' or 'digest', default is 'basic',
          'irmc_client_timeout': timeout, default is 60,
          ...
        }
    :param method: request method such as 'GET', 'POST'
    :param path: url path for eLCM request
    :returns: requests.Response from SCCI server
    :raises SCCIInvalidInputError: if port and/or auth_method params
             are invalid
    :raises SCCIClientError: if SCCI failed
    """
    host = irmc_info['irmc_address']
    port = irmc_info.get('irmc_port', 443)
    auth_method = irmc_info.get('irmc_auth_method', 'basic')
    userid = irmc_info['irmc_username']
    password = irmc_info['irmc_password']
    client_timeout = irmc_info.get('irmc_client_timeout', 60)

    # Request headers, params, and data
    headers = kwargs.get('headers', {'Accept': 'application/json'})
    params = kwargs.get('params')
    data = kwargs.get('data')

    auth_obj = None
    try:
        protocol = {80: 'http', 443: 'https'}[port]
        auth_obj = {
            'basic': requests.auth.HTTPBasicAuth(userid, password),
            'digest': requests.auth.HTTPDigestAuth(userid, password)
        }[auth_method.lower()]

    except KeyError:
        raise scci.SCCIInvalidInputError(
            ("Invalid port %(port)d or " +
             "auth_method for method %(auth_method)s") % {
                 'port': port,
                 'auth_method': auth_method
             })

    try:
        r = requests.request(method,
                             protocol + '://' + host + path,
                             headers=headers,
                             params=params,
                             data=data,
                             verify=False,
                             timeout=client_timeout,
                             allow_redirects=False,
                             auth=auth_obj)
    except requests.exceptions.RequestException as requests_exception:
        raise scci.SCCIClientError(requests_exception)

    # Process status_code 401
    if r.status_code == 401:
        raise scci.SCCIClientError('UNAUTHORIZED')

    return r