def login(self, host, user=None, password=None, session_key=None):
        """
        Establishes a session with the provided iLO sub-system using the
        provided credentials

        Example:
          | DL ILO API Login | 192.168.20.10 | Administrator | iwf01help |

        :param str host: IP or FQDN of the iLO Sub-system
        :param str user: Name of the user known in the iLO realm
        :param str password: Password of the provided user
        :param session_key: Authorization key for supporting Single Sign ON
        :return: None
        """
        self.ilo_host = host
        self.ilo_user = user
        self.ilo_pass = password
        self.ilo_sso = session_key

        try:
            self.client = RedfishClient(host=host, user=user, password=password,
                                        session_key=session_key)
        except:     # no-qa
            logger.debug("Unable to reach {}".format(host))
            raise AssertionError("Failed to establish communication")
    def _set_power_state(self, state):
        """
        Applies the requested power state on the system.
        :param str state: Supported values are On, ForceOff, ForceRestart,
                          PushPowerButton
        :return: :bool True on success else False
        """
        uri = self.client.get_resource_uris('ComputerSystem.')[0]
        # For Rack server, there would ideally be only one item.

        if self.client.type_path.defs.isgen9:
            r = self.client.post(uri['@odata.id'], {'Action': 'Reset',
                                                    'ResetType': state})
        else:
            pr = self.client.get(uri['@odata.id'])

            if pr.status == 200:
                p = pr.dict['Actions']['#ComputerSystem.Reset']['target']
            else:
                _ = 'Unable to gather resource path to perform {}'.format(state)
                logger.debug(_)
                return False

            r = self.client.post(p, {'Action': 'ComputerSystem.Reset',
                                     'ResetType': state})

        e = self.client.get_message(r)
        if e.get('error_code') == 'Success':
            return True
        elif e.get('error_code') == 'InvalidOperationForSystemState':
            # System was in the requested state hence passing it
            logger.info(e.get('error_info'))
            return True

        return False
Example #3
0
    def _validate_and_set_host(self, host):
        """
        Verifies and adds the target information to the body
        :param dict host: Contains
        :return bool: True if the payload is updated with host information
        """
        attrs = ['ipv4', 'user', 'password']

        if not host.get('os'):
            log.debug('Missing required attribute: os')
            return False

        if not set(attrs).issubset(host.keys()):
            m = 'Found attributes: {}'.format(host.keys())
            m += '\nRequired attributes: {}'.format(attrs)
            log.info(m)
            return False

        if host.get('datacenter'):
            if host.get('manager') is None:
                log.info('Missing required attribute: manager')
                return False

        self.body['host'] = deepcopy(host)
        log.debug('Host information found {}'.format(host))
        return True
    def get_resource_uris(self, types):
        """
        Returns the system resource links matching the request type
        :param str types: Type to be searched
        :return list: List of system resources
        """
        data = list()

        for i in self.SYS_RESOURCE['resources']:
            found = False

            if i.get('@odata.type', None) and types.lower() in \
                    i.get('@odata.type').lower():
                for e in self.SYS_RESOURCE['resources']:
                    if (i['@odata.type'] + '/settings/').lower() == \
                            (e['@odata.id']).lower():
                        found = True
                        break

                if not found:
                    data.append(i)

        if not data:
            logger.debug("{} resource or feature not supported".format(types))
            raise AssertionError("Not implemented feature")

        return data
    def wait_till_finished_post(self, timeout=20, poll=10):
        """
        Waits till the system has completed Post Discovery stage and is
        booting the OS or searching for boot loader. Useful in cases where the
        manager is applying settings and rebooting

        Example:
          | ${r}=   | DL ILO API Return After POST Complete | <min> | <sec>

        :param int timeout: Timeout value in minutes
        :param int poll: Polling interval in seconds
        :return: True when POST is completed within time frame else False
        """
        if self.get_power_state_server() == 'Off':
            self.set_power_state_on()

        timeout = datetime.now() + timedelta(minutes=timeout)
        while timeout > datetime.now():
            logger.debug("Sleeping for {} seconds before poll".format(poll))
            sleep(poll)

            s = self.get_post_state_server()
            if s == 'InPostDiscoveryComplete' or s == 'FinishedPost':
                # System manager will request for a server reboot after this
                # stage when there pending settings to be applied so sleep and
                # if state is the same break
                sleep(3)
                rs = self.get_post_state_server()
                if rs == 'InPostDiscoveryComplete' or rs == 'FinishedPost':
                    return True

        logger.debug("Timeout: System has not completed POST")
        return False
    def _get_base_registry(self):
        """
        Returns the list of message registries
        :return: dict
        """
        resp = self.get(uri='/redfish/v1/Registries/')
        msg = dict()

        for e in resp.dict['Members']:
            if not [x for x in ['/Base/', '/iLO/'] if x in e['@odata.id']]:
                continue
            else:
                reg = self.get(uri=e['@odata.id'])

            for l in reg.dict['Location']:
                loc = l['Uri']['extref'] if 'extref' in l['Uri'] else l['Uri']
                r = self.get(uri=loc)

                if r.status == 200:
                    msg[r.dict['RegistryPrefix']] = r.dict['Messages']
                else:
                    m = "{} not found at {}".format(r.dict['RegistryPrefix'],
                                                    loc)
                    logger.debug(m)

        return msg
Example #7
0
    def upload_folder_from_local(self, local_path, remote_path):
        # check if local_path is a folder
        if not os.path.isdir(local_path):
            return False, {
                'except_obj':
                IOError(
                    "Specified :local_path '%s' not exist or not a folder!" %
                    local_path),
                'line':
                sys._getframe().f_lineno
            }

        self._open_sftp()

        # firstly create remote_path is not exist
        self.create_folder(remote_path)

        for dirpath, dirnames, filenames in os.walk(local_path):
            if dirnames:
                # create folder on remote
                for dirname in dirnames:
                    folder_to_create = os.path.join(remote_path,
                                                    dirname).replace(
                                                        os.path.sep, '/')
                    # create if not exist
                    try:
                        self.sftp.listdir(folder_to_create)
                    except IOError as ex:
                        if ex.errno == errno.ENOENT:
                            logger.debug("Creating folder '%s' on remote" %
                                         folder_to_create)
                            self.sftp.mkdir(folder_to_create)
                        else:
                            exc_type, exc_obj, exc_tb = sys.exc_info()
                            return False, {
                                'except_obj': ex,
                                'line': exc_tb.tb_lineno
                            }

            if filenames:
                # do single upload
                for filename in filenames:
                    local_file_path = os.path.join(dirpath, filename).replace(
                        os.path.sep, '/')
                    remote_file_path = os.path.join(
                        remote_path,
                        local_file_path.replace(os.path.sep, '/').replace(
                            local_path.replace(os.path.sep, '/'),
                            '').lstrip('/')).replace(os.path.sep, '/')
                    logger.debug("Uploading file on remote: '%s' => '%s'" %
                                 (local_file_path, remote_file_path))
                    self.sftp.put(local_file_path, remote_file_path)

        return True, None
 def ilo_wrap(self, *args, **kwargs):
     """
     Method that verifies the connection is authenticated
     :param self: The object
     :param args: Linear list of arguments
     :param kwargs: List of key value pairs
     :return: Results of the specified method.
     """
     if self.client is None:
         logger.debug("DEBUG: ILO communication not established.")
         raise AssertionError("iLO login is required")
     return func(self, *args, **kwargs)
    def _get_resource_directory(self):
        """
        Returns the list of system resources
        :return: Dictionary
        """
        resp = self.get(uri='/redfish/v1/resourcedirectory/')

        if resp.status == 200:
            return {'resources': resp.dict['Instances']}
        else:
            logger.debug("Unable to find resource directory.")
            raise AssertionError("Resource directory is missing.")
def get_firmware_bundle(fw_path, fw_name=''):
    if os.path.exists(fw_path):
        spp_folder = fw_path
    else:
        return False
    spp_list = [each for each in os.listdir(spp_folder) if each.startswith(fw_name)]
    if not spp_list:
        logger.debug("Please upload a SPP to folder '%s' before test" % spp_folder)
        return False
    spp_name = sorted(spp_list, reverse=True)[0]

    absolute_path = spp_folder + '\\' + spp_name
    if not os.path.isfile(absolute_path):
        return False

    return absolute_path
    def get_power_state_server(self):
        """
        Retrieves the power status of the system

        Example:
          | ${pwr}=     | DL ILO API Get Power State |

        :return str:  On | Off | Unknown | Reset
        """
        uri = self.client.get_resource_uris('ComputerSystem.')[0]
        r = self.client.get(uri['@odata.id'])

        if r.status != 200:
            logger.debug("Unable to retrieve the power state.")
            return 'Unknown'

        return r.dict['PowerState']
    def _remote_cmd(self, cmd, block=True):
        """
        Executes the given command on the remote system and returns the outpu
        :param cmd: Command to be executed on the remote system
        :type: str
        :return str: Output
        """
        r = remote_cmd(host_ip=self.host['ipv4'],
                       username=self.host['user'],
                       password=self.host['password'],
                       command=cmd,
                       block=block)

        if r.get('status').lower() == "failed":
            log.debug('Command: {}\nOutput: {}'.format(cmd, r['error']))
            return r.get('error') if r.get('error') else False

        if r.get('status').lower() == "success":
            log.debug('Command: {}\nOutput: {}'.format(cmd, r['output']))
            return r['output'] if r['output'] else True
Example #13
0
    def _add_network_profile(self, net_profile):
        """
        In conjunction with ports, creates the configuration dictionary
        :param dict net_profile: Network profile information
        :return bool: True when the configuration is added to self.body
        """
        net_types = list()

        if 'redhat' in self.body['host']['os'].lower() or \
                'red hat' in self.body['host']['os'] or \
                'rhel' in self.body['host']['os']:
            net_types = ['ethernet', 'bond', 'team']
        elif 'vmware' in self.body['host']['os'].lower():
            net_types = ['vss', 'vds']

        if not net_profile.get('type') or \
                not net_profile['type'].lower() in net_types:
            log.info('Unknown network config: {}'.format(net_profile['type']))
            log.info('Supported network configurations: {}'.format(net_types))
            return False

        net_uri = self._get_network_uri(net_profile.get('ov_network'))
        if net_uri is None:
            return False

        if net_uri not in self.ports:
            log.info('Network not part of server profile connections {}')
            return False

        self.net_profile = deepcopy(net_profile)

        if 'redhat' in self.body['host']['os'].lower() or \
                'red hat' in self.body['host']['os'] or \
                'rhel' in self.body['host']['os']:
            return self._add_rhel_config(net_profile['ov_network'], net_uri)
        elif 'vmware' in self.body['host']['os'].lower():
            return self._add_vmware_config(net_uri)

        log.debug('Unknown network profile type {}'.format(
            net_profile['type']))
        return False
    def get_post_state_server(self):
        """
        Retrieves the Post state of the system

        Example:
          | ${state}=   | DL ILO API Get Post State

        :return str:  Unknown | Reset | PowerOff | InPost | FinishedPost | \
                      InPostDiscoveryComplete
        """
        uri = self.client.get_resource_uris('ComputerSystem.')[0]
        r = self.client.get(uri['@odata.id'])

        if r.status != 200:
            logger.debug("Unable to retrieve the Post State of the server.")
            return 'Unknown'

        if self.client.type_path.defs.isgen9:
            return r.dict['Oem']['Hp']['PostState']
        else:
            return r.dict['Oem']['Hpe']['PostState']
Example #15
0
    def _get_network_uri(self, name):
        """
        Retrieve the networkUri from OneView based on the argument
        :param str name: Network name
        :return str: Network's URI corresponding to OV
        """
        p = '?&filter="\'name\'==\'{}\'"'.format(name.lower())
        r = self.fusion_api_get_ethernet_networks(param=p)

        if r.get('count') == 0:
            r = self.fusion_api_get_network_set(param=p)
            if r.get('count') == 0:
                log.info('{} not found in OneView'.format(name))
                return None

        if r.get('count') > 1:
            log.info('Found more than one match for {}'.format(name))
            return None

        log.debug('Retrieved the network uri for {}'.format(name))
        return r.get('members')[0]['uri']
Example #16
0
    def call_cmd(self, cmd, realout=False):
        out = DataObj()
        out.add_property('stdout', None)
        out.add_property('stderr', None)
        out.add_property('code', 1)
        stdin, stdout, stderr = self.ssh.exec_command(cmd)

        if realout is False:
            out.add_property('stdout', stdout.read())
            out.add_property('stderr', stdout.read())
        else:
            outputs = []
            while not stdout.channel.exit_status_ready():
                # Only print data if there is data to read in the channel
                if stdout.channel.recv_ready():
                    rl, wl, xl = select.select([stdout.channel], [], [], 0.0)
                    if len(rl) > 0:
                        # Print data from stdout
                        data = stdout.channel.recv(1024)
                        outputs.append(data)
                        # logger.debug(data, also_console=True, newline=False, time_prefix=False)
                        logger.debug(data)
            else:
                data = stdout.channel.recv(1024)
                outputs.append(data)
                # logger._debug(data, also_console=True, newline=False, time_prefix=False)
                logger.debug(data)
            out.add_property('stdout', ''.join(outputs))
            out.add_property('stderr', stderr.read())
            # logger._debug('', time_prefix=False)
            logger.debug('')
        out.code = stdout.channel.recv_exit_status()
        return out
    def reset_ilo(self):
        """
        Performs a reset of the iLO sub-system

        Example:
          | ${r}=   | DL ILO API Reset iLO Manager |

        :return: :bool True on success else False
        """
        uris = self.client.get_resource_uris('Manager.')
        # For rack server, there would only be one item however there are
        # instances where DL's holds multiple managers. One scenario is after
        # running SUT outside of OneView. So iterate through the managers

        for uri in uris:
            if self.client.type_path.defs.isgen9:
                r = self.client.post(uri['@odata.id'], {'Action': 'Reset'})
            else:
                pr = self.client.get(uri['@odata.id'])

                if pr.status == 200:
                    p = pr.dict['Actions']['#Manager.Reset']['target']
                else:
                    _ = "Unable to perform reset at {}".format(uri['@odata.id'])
                    logger.debug(_)
                    continue

                r = self.client.post(p, {'Action': 'Manager.Reset'})

            e = self.client.get_message(r)
            if e.get('error_code') == 'ResetInProgress':
                logger.debug('Sleeping for 90 seconds before verification')
                # Waking up to early results in-complete Resource entries which
                # cause feature not implemented errors.
                sleep(90)
                self.login(self.ilo_host, self.ilo_user, self.ilo_pass,
                           self.ilo_sso)
                return True

        return False
Example #18
0
    def _network_config_generator(self, sp_url, host_info, nets):
        """
        Keyword to generate the required payload for configuring the target
        system networks

        Usage
          ${body}=    Create Payload For OS Networks Configuration |
          ...             <ov_server_profile_url> |
          ...             <host_info> |
          ...             <network_profiles> |

        [Returns]
          A dictionary which would be an input to 'Configure OS Networks'

        :param str sp_url: Target system's OneView server profile URL
        :param dict host_info: Target system's credentials and type
        :param list nets: List of network profiles
        :return:
        """
        sp = self.fusion_api_get_server_profiles(uri=sp_url)

        if sp['status_code'] != 200:
            log.info("Invalid OneView Server Profile URL: {}".format(sp_url))
            return self.body

        if int(sp['type'].split('V')[-1]) < 8:
            self._set_ports(sp.get('connections', list()))
        else:
            self._set_ports(sp.get('connectionSettings').get('connections'))

        if not self._validate_and_set_host(host_info):
            log.info("Invalid target server information: {}".format(host_info))
            return self.body

        for net in nets:
            if self._add_network_profile(net):
                log.debug('{} network configuration created.'.format(net))

        return self.body if len(self.body['config']) else dict()
Example #19
0
 def open_ssh(self, host, username, password):
     # if call this method again when connection is keeping.
     # suppose we want to disconnect current SSH connection then connect to another host
     if self.connected is False:
         try:
             self.ssh = paramiko.SSHClient()
             self.sftp = None
             self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
             self.ssh.connect(host,
                              username=username,
                              password=password,
                              look_for_keys=False)
             self.connected = True
             logger.debug("Connected to %s" % host)
         except Exception as e:
             self.connected = False
             logger.debug("Connected to %s failed with the exception %s" %
                          (host, e.message))
     # close current connect & connect to another host
     else:
         self.close_ssh()
         self.open_ssh(host, username, password)
    def get_message(self, resp):
        """
        Returns the error message code and description
        :param resp: RestResponse object
        :return dict: Error code & Description
        """
        if not self.MSG_REGISTRY:
            logger.debug("No message registry found.")
            return dict()

        try:
            r = resp.dict
            # The response would be of the below format
            # {"error":{"@Message.ExtendedInfo": \
            # [{"MessageId":"iLO.0.10.ResetInProgress"}]
            n = r['error']['@Message.ExtendedInfo'][0]['MessageId'].split('.')
        except:
            logger.debug("No extended error information.")
            return dict()

        for err in self.MSG_REGISTRY:
            if err != n[0]:
                continue

            for e in self.MSG_REGISTRY[err]:
                if e == n[3]:
                    code = n[3]
                    desc = self.MSG_REGISTRY[err][e]['Description']
                    m = "iLO Error Code:\t {}".format(code)
                    m += "\nDescription:\t{}".format(desc)

                    logger.debug(m)
                    return {'error_code': code, 'error_info': desc}

        # Unexpected code path
        logger.debug("There exists an error code with no description")
        return {'error_code': n[3], 'error_info': None}
Example #21
0
    def _get_network_addr(self, uri, vmware=False):
        """
        Returns a dictionary that holds config['networks'] entry
        :param str uri: OneView network information
        :param bool vmware: If the requestor is vmware
        :return dict: config['networks'] dictionary
        """
        n = self.fusion_api_get_ethernet_networks(uri=uri)
        if n is None:
            log.debug('No network information for {}'.format(uri))
            return None

        b = dict({'dhcp': True, 'vlan': n.get('vlanId')})

        if vmware:
            b.update({'name': n['name'], 'type': n.get('purpose')})

        # DHCP is set till the method is able to allocate an IP address
        if n.get('subnetUri', None) is None:
            log.debug('No associated network for {}'.format(uri))
            return b

        s = self.fusion_api_get_ipv4_subnet(uri=n.get('subnetUri'))
        if s is None:
            log.debug('No subnet information for {}'.format(n['subnetUri']))
            return b

        a = self.fusion_api_allocate_ipv4_subnet({'count': 1}, s['uri'])
        if a.get('status_code') != 200:
            log.debug('No available IPv4 address.')
            return b

        b['dhcp'] = False
        b.update({'ipv4': a['idList'][0], 'netmask': s['subnetmask']})

        return b
Example #22
0
    def _add_rhel_config(self, name, uri):
        """
        Creates the network configuration for RHEL based systems
        :param str name: Name of the network name
        :param str uri: OneView's networkUri
        :return bool: True when network configuration is appended to body
        """
        port_count = len(self.ports[uri])
        if self.net_profile['type'].lower() == 'ethernet' and port_count != 1:
            _ = 'Invalid number of ports {}'.format(name)
            log.info(_)
            return False

        if (self.net_profile['type'].lower() == 'bond' or
            self.net_profile['type'].lower() == 'team') and \
                port_count != 2:
            _ = 'Invalid number of port for {}'.format(name)
            log.info(_)
            return False

        cfg = {
            'name': self.net_profile.get('name', name),
            'type': self.net_profile['type'],
            'ports': self.ports[uri]
        }

        if self.net_profile['type'].lower() == 'bond':
            cfg.update({'bond_opts': self.net_profile['bond_opts']})
        elif self.net_profile['type'].lower() == 'team':
            cfg.update({
                'team_opts': self.net_profile['team_opts'],
                'team_port_cfg': self.net_profile['team_port_cfg']
            })

        nets = list()
        if 'ethernet-network' in uri:
            n = self._get_network_addr(uri)
            if n is not None:
                # VLAN is configured on the interconnect
                if n.get('vlan'):
                    # Removing VLAN as it is a single network and Oneview
                    # configures the same on the interconnect downlink port
                    del n['vlan']

                nets.append(n)
        elif 'network-set' in uri:
            r = self.fusion_api_get_network_set(uri=uri)
            if r.get('nativeNetworkUri'):
                n = self._get_network_addr(r['nativeNetworkUri'])
                if n is not None:
                    if n.get('vlan'):
                        # Removing VLAN as it is native to network set and
                        # configured by Oneview on the interconnect downlink
                        del n['vlan']

                    nets.append(n)

            for u in r.get('networkUris', []):
                if u == r.get('nativeNetworkUri'):
                    log.debug('Ignoring this network as it is native')
                    continue

                n = self._get_network_addr(u)
                if n is not None:
                    nets.append(n)
        else:
            log.info('Unknown OneView network connection: {}'.format(uri))
            log.info('Supported types: ethernet, network-set')
            return False

        if nets:
            cfg['networks'] = deepcopy(nets)
            self.body['config'].append(cfg)
            log.debug('Network config: {}'.format(cfg))
            return True

        log.debug('No network information retrieved... skipping')
        return False
Example #23
0
    def _add_vmware_config(self, uri):
        """
        Creates the network configuration for VMware based systems
        :param str uri: OneView's networkUri
        :return bool: True when network configuration is appended to body
        """
        if self.net_profile.get('name') is None:
            log.info('Virtual Switch name is required')
            return False

        if self.net_profile.get('type').lower() == 'vds':
            attrs = ['manager', 'datacenter', 'cluster']

            if not set(attrs).issubset(self.body['host'].keys()):
                m = 'Missing required attributes.'
                m += "Additional required attributes are\t{}".format(attrs)
                log.info(m)
                return False

        cfg = dict({
            'name': self.net_profile['name'],
            'type': self.net_profile['type'],
            'ports': self.ports[uri]
        })

        nets = list()
        if 'ethernet-network' in uri:
            n = self._get_network_addr(uri, True)
            if n is None:
                return False

            if self.net_profile.get('networks') and \
                    self.net_profile['networks'].get(n['vlan']):
                if 'policy' in self.net_profile['networks'][n['vlan']]:
                    n['policy'] = \
                        self.net_profile['network'][n['vlan']]['policy']

                if 'vmk' in self.net_profile['network'][n['vlan']]:
                    n['vmk'] = self.net_profile['network'][n['vlan']]['vmk']
                else:
                    # No vmkernel port would be created
                    n['vmk'] = False
            else:
                n['vmk'] = False

            # VLAN is configured on the downlink port
            del n['vlan']
            nets.append(n)
        elif 'network-set' in uri:
            ns = self.fusion_api_get_network_set(uri=uri)
            if ns.get('nativeNetworkUri'):
                n = self._get_network_addr(ns['nativeNetworkUri'], True)
                if n is not None:
                    if self.net_profile.get('networks') and \
                            self.net_profile['networks'].get(n['vlan']):
                        if 'policy' in self.net_profile['networks'][n['vlan']]:
                            n['policy'] = \
                                self.net_profile['networks'][n['vlan']]['policy']

                        if 'vmk' in self.net_profile['networks'][n['vlan']]:
                            n['vmk'] = \
                                self.net_profile['networks'][n['vlan']]['vmk']
                        else:
                            n['vmk'] = False
                    else:
                        n['vmk'] = False

                    del n['vlan']
                    nets.append(n)

            for u in ns.get('networkUris', []):
                if u == ns.get('nativeNetworkUri'):
                    log.debug('Ignoring this network as it is a native one.')
                    continue

                n = self._get_network_addr(u, True)
                if n is None:
                    continue

                if self.net_profile.get('networks') and \
                        self.net_profile['networks'].get(n['vlan']):
                    if 'policy' in self.net_profile['networks'][n['vlan']]:
                        n['policy'] = \
                            self.net_profile['networks'][n['vlan']]['policy']

                    if 'vmk' in self.net_profile['networks'][n['vlan']]:
                        n['vmk'] = \
                            self.net_profile['networks'][n['vlan']]['vmk']
                    else:
                        n['vmk'] = False
                else:
                    n['vmk'] = False

                nets.append(n)

            cfg['active'] = self.net_profile.get('active', len(cfg['ports']))
        else:
            log.info('Unsupported network connection {}'.format(uri))
            log.info('Supported types: vss, vds')

        if nets:
            cfg['networks'] = nets
            self.body['config'].append(cfg)
            log.debug('Network config: {}'.format(cfg))
            return True

        log.debug('No network information was retrieved... skipping')
        return False