def _get_members(self, url): data = self.request('GET', url, cmd='get_members') try: return data['Members'] except KeyError as e: raise SelfServerException('Get KeyError %s' % e.args)
def upload (self, method, resource, files, headers=None, cmd=''): httpheaders = headers or OpenBMCRest.headers url = resource if not url.startswith(HTTP_PROTOCOL): url = self.root_url + resource request_cmd = self._log_request(method, url, httpheaders, files=files, cmd=cmd) try: response = self.session.request_upload(method, url, httpheaders, files) except SelfServerException as e: self._print_error_log(e.message, cmd=cmd) raise try: data = json.loads(response) except ValueError: error = 'Received wrong format response when running command \'%s\': %s' % \ (request_cmd, response) self._print_error_log(error, cmd=cmd) raise SelfServerException(error) if data['message'] != '200 OK': error = 'Failed to upload update file %s : %s-%s' % \ (files, data['message'], \ ''.join(data['data']['description'])) self._print_error_log(error, cmd=cmd) raise SelfClientException(error, code) self._print_record_log(data['message'], cmd=cmd) return True
def test_login_value_error(self): self.rf_rest.request = mock.Mock(side_effect=SelfServerException( 'Received wrong format response: xxxxxx')) with pytest.raises(SelfServerException) as excinfo: self.rf_rest.login() assert excinfo.type == SelfServerException assert 'Received wrong format response:' in str(excinfo.value)
def get_nic_netinfo(self, nic): path = RSPCONFIG_NETINFO_URL['get_nic_netinfo'].replace('#NIC#', nic) data = self.request('GET', path, cmd='get_nic_netinfo') try: netinfo = {} for k, v in data.items(): dev, match, netid = k.partition("/ipv4/") if 'LinkLocal' in v["Origin"] or v["Address"].startswith( "169.254"): msg = "Found LinkLocal address %s for interface %s, Ignoring..." % ( v["Address"], dev) self._print_record_log(msg, 'get_netinfo') continue utils.update2Ddict(netinfo, netid, 'ip', v['Address']) utils.update2Ddict(netinfo, netid, 'ipsrc', v['Origin'].split('.')[-1]) utils.update2Ddict(netinfo, netid, 'netmask', v['PrefixLength']) utils.update2Ddict(netinfo, netid, 'gateway', v['Gateway']) return netinfo except KeyError: error = 'Received wrong format response: %s' % data raise SelfServerException(error)
def request (self, method, resource, headers=None, payload=None, timeout=30, cmd=''): httpheaders = headers or OpenBMCRest.headers url = resource if not url.startswith(HTTP_PROTOCOL): url = self.root_url + resource data = None if payload: data=json.dumps(payload) self._log_request(method, url, httpheaders, data=data, cmd=cmd) try: response = self.session.request(method, url, httpheaders, data=data, timeout=timeout) return self.handle_response(response, cmd=cmd) except SelfServerException as e: if cmd == 'login': e.message = "Login to BMC failed: Can't connect to {0} {1}.".format(e.host_and_port, e.detail_msg) else: e.message = 'BMC did not respond. ' \ 'Validate BMC configuration and retry the command.' self._print_error_log(e.message, cmd) raise except ValueError: error = 'Received wrong format response: %s' % response self._print_error_log(error, cmd) raise SelfServerException(error)
def request(self, method, resource, headers=None, payload=None, timeout=30, cmd=''): httpheaders = headers or OpenBMCRest.headers url = resource if not url.startswith(HTTP_PROTOCOL): url = self.root_url + resource data = None if payload: data = json.dumps(payload) self._log_request(method, url, httpheaders, data=data, cmd=cmd) try: response = self.session.request(method, url, httpheaders, data=data, timeout=timeout) return self.handle_response(response, cmd=cmd) except SelfServerException as e: e.message = 'Error: BMC did not respond. ' \ 'Validate BMC configuration and retry the command.' self._print_record_log(e.message, cmd) raise except ValueError: error = 'Error: Received wrong format response: %s' % response self._print_record_log(error, cmd) raise SelfServerException(error)
def get_sensor_info(self): sensor_data = self.request('GET', SENSOR_URL, cmd='get_sensor_info') try: sensor_dict = {} for k, v in sensor_data.items(): if 'Unit' in v: unit = v['Unit'].split('.')[-1] if unit in SENSOR_UNITS: label = k.split('/')[-1].replace('_', ' ').title() value = v['Value'] scale = v['Scale'] value = value * pow(10, scale) value = '{:g}'.format(value) if unit not in sensor_dict: sensor_dict[unit] = [] sensor_dict[unit].append( '%s: %s %s' % (label, value, SENSOR_UNITS[unit])) elif 'units' in v and 'value' in v: label = k.split('/')[-1] value = v['value'] sensor_dict[label] = ['%s: %s' % (label, value)] return sensor_dict except KeyError: error = 'Received wrong format response: %s' % sensor_data raise SelfServerException(error)
def parse_eventlog_data(self, eventlog_data): # Check if policy table file is there ras_event_mapping = {} if os.path.isfile(RAS_POLICY_TABLE): with open(RAS_POLICY_TABLE) as data_file: policy_hash = json.load(data_file) if policy_hash: ras_event_mapping = policy_hash['events'] else: self.messager.info(RAS_POLICY_MSG) data_file.close() else: self.messager.info(RAS_POLICY_MSG) try: eventlog_dict = {} for key, value in sorted(eventlog_data.items()): id, event_log_line = self.parse_eventlog_data_record( value, ras_event_mapping) if int(id) != 0: eventlog_dict[str(id)] = event_log_line if not eventlog_dict: # Nothing was returned from BMC eventlog_dict['0'] = 'No attributes returned from the BMC.' return eventlog_dict except KeyError: error = 'Received wrong format response: %s' % eventlog_data raise SelfServerException(error)
def test_request_login_connect_failed(self): login_data = { "UserName": self.rf_rest.username, "Password": self.rf_rest.password } self.rf_rest.session.request = mock.Mock(side_effect=SelfServerException('Login to BMC failed: Can\'t connect to')) with pytest.raises(SelfServerException) as excinfo: self.rf_rest.request('POST', self.session_url, headers=self.headers, payload=login_data, cmd='login') assert excinfo.type == SelfServerException assert 'Login to BMC failed: Can\'t connect to' in str(excinfo.value)
def list_dump_info(self): dump_data = self.request('GET', DUMP_URLS['list'], cmd='list_dump_info') try: dump_dict = {} for key, value in dump_data.items(): if 'Size' not in value or 'Elapsed' not in value: continue key_id = int(key.split('/')[-1]) timestamp = value['Elapsed'] gen_time = time.strftime("%m/%d/%Y %H:%M:%S", time.localtime(timestamp)) dump_dict.update( {key_id: { 'Size': value['Size'], 'Generated': gen_time }}) return dump_dict except KeyError: error = 'Received wrong format response: %s' % dump_data raise SelfServerException(error)
def reboot(self, optype='boot', **kw): node = kw['node'] obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback, debugmode=self.debugmode, verbose=self.verbose) try: obmc.login() states = obmc.list_power_states() status = obmc.get_host_state(states) new_status = '' if optype == 'reset' and status in ['Off', 'chassison']: status = openbmc.RPOWER_STATES['Off'] self.callback.info('%s: %s' % (node, status)) else: if status not in ['Off', 'off']: obmc.set_power_state('off') self.callback.update_node_attributes( 'status', node, POWER_STATE_DB['off']) off_flag = False start_timeStamp = int(time.time()) for i in range(0, 30): gevent.sleep(2) try: states = obmc.list_power_states() status = obmc.get_host_state(states) if openbmc.RPOWER_STATES.get(status) == 'off': off_flag = True break except SelfServerException as e: continue end_timeStamp = int(time.time()) if not off_flag: error = 'Error: Sent power-off command but state did not change ' \ 'to off after waiting %s seconds. (State= %s).' % (end_timeStamp - start_timeStamp, status) raise SelfServerException(error) for i in range(0, 2): try: ret = obmc.set_power_state('on') self.callback.update_node_attributes( 'status', node, POWER_STATE_DB['on']) self.callback.info('%s: %s' % (node, 'reset')) return except SelfServerException as e: self.callback.syslog('%s: %s' % (node, e.message)) gevent.sleep(1) continue self.callback.error(e.message, node) except (SelfServerException, SelfClientException) as e: self.callback.error(e.message, node)
def get_bmc_state(self): try: state = self.request('GET', BMC_URLS['state']['path'], cmd='get_bmc_state') return {'bmc': state.split('.')[-1]} except KeyError: error = 'Received wrong format response: %s' % state raise SelfServerException(error)
def test_login_not_respond(self): self.rf_rest.request = mock.Mock(side_effect=SelfServerException( 'BMC did not respond. Validate BMC configuration and retry the command.' )) with pytest.raises(SelfServerException) as excinfo: self.rf_rest.login() assert excinfo.type == SelfServerException assert 'BMC did not respond. Validate BMC configuration and retry the command.' in str( excinfo.value)
def get_netinfo(self): data = self.request('GET', RSPCONFIG_NETINFO_URL['get_netinfo'], cmd="get_netinfo") try: netinfo = {} for k, v in data.items(): if 'network/config' in k: if 'HostName' in v: netinfo["hostname"] = v["HostName"] if 'DefaultGateway' in v: netinfo["defaultgateway"] = v["DefaultGateway"] continue dev, match, netid = k.partition("/ipv4/") if netid: nicid = dev.split('/')[-1] if nicid not in netinfo: netinfo[nicid] = {} if 'LinkLocal' in v["Origin"] or v["Address"].startswith( "169.254"): msg = "Found LinkLocal address %s for interface %s, Ignoring..." % ( v["Address"], dev) self._print_record_log(msg, 'get_netinfo') # Save Zero Conf information netinfo[nicid]["zeroconf"] = v["Address"] continue if 'ip' in netinfo[nicid]: msg = "%s: Another valid ip %s found." % (node, v["Address"]) self._print_record_log(msg, 'get_netinfo') del netinfo[nicid] netinfo[ 'error'] = 'Interfaces with multiple IP addresses are not supported' break utils.update2Ddict(netinfo, nicid, "ipsrc", v["Origin"].split('.')[-1]) utils.update2Ddict(netinfo, nicid, "netmask", v["PrefixLength"]) utils.update2Ddict(netinfo, nicid, "gateway", v["Gateway"]) utils.update2Ddict(netinfo, nicid, "ip", v["Address"]) utils.update2Ddict(netinfo, nicid, "ipobj", netid) if dev in data: info = data[dev] utils.update2Ddict(netinfo, nicid, "vlanid", info.get("Id", "Disable")) utils.update2Ddict(netinfo, nicid, "mac", info["MACAddress"]) ntpservers = None tmp_ntpservers = ''.join(info["NTPServers"]) if tmp_ntpservers: ntpservers = tmp_ntpservers utils.update2Ddict(netinfo, nicid, "ntpservers", ntpservers) return netinfo except KeyError: error = 'Received wrong format response: %s' % data raise SelfServerException(error)
def test_request_connect_failed(self): self.rf_rest.session.request = mock.Mock(side_effect=SelfServerException( 'BMC did not respond. Validate BMC configuration and retry the command.' )) with pytest.raises(SelfServerException) as excinfo: self.rf_rest.request('GET', self.manager_url, headers=self.headers) assert excinfo.type == SelfServerException assert 'BMC did not respond. Validate BMC configuration and retry the command.' in str( excinfo.value)
def get_systems_power_state(self): members = self._get_members(SYSTEMS_URL) target_url = members[0]['@odata.id'] data = self.request('GET', target_url, cmd='get_systems_power_state') try: return data['PowerState'] except KeyError as e: raise SelfServerException('Get KeyError %s' % e.args)
def _get_boot_actions(self): members = self._get_members(SYSTEMS_URL) target_url = members[0]['@odata.id'] data = self.request('GET', target_url, cmd='get_boot_actions') try: actions = data['Boot']['*****@*****.**'] except KeyError as e: raise SelfServerException('Get KeyError %s' % e.args) return (target_url, actions)
def list_power_states(self): states = self.request('GET', RPOWER_URLS['state']['path'], cmd='list_power_states') #filter non used states try: host_stat = states[PROJECT_URL + '/state/host0']['CurrentHostState'] chassis_stat = states[PROJECT_URL + '/state/chassis0']['CurrentPowerState'] return {'host': host_stat.split('.')[-1], 'chassis': chassis_stat.split('.')[-1]} except KeyError: error = 'Received wrong format response: %s' % states raise SelfServerException(error)
def _get_power_actions(self): members = self._get_members(SYSTEMS_URL) target_url = members[0]['@odata.id'] data = self.request('GET', target_url, cmd='get_power_actions') try: actions = data['Actions'][system_reset_string][reset_type_string] target_url = data['Actions'][system_reset_string]['target'] except KeyError as e: raise SelfServerException('Get KeyError %s' % e.args) return (target_url, actions)
def get_beacon_info(self): beacon_data = self.request('GET', LEDS_URL, cmd='get_beacon_info') try: beacon_dict = {} for key, value in beacon_data.items(): key_id = key.split('/')[-1] if key_id in LEDS_KEY_LIST: beacon_dict[key_id] = value['State'].split('.')[-1] return beacon_dict except KeyError: error = 'Received wrong format response: %s' % beacon_data raise SelfServerException(error)
def get_apis_values(self, key): attr_info = RSPCONFIG_APIS[key] if 'get_url' not in attr_info: raise SelfServerException("Reading %s failed, not url available" % key) get_url = attr_info['baseurl']+attr_info['get_url'] method = 'GET' if 'get_method' in attr_info: method = attr_info['get_method'] data = None if 'get_data' in attr_info: data={"data": attr_info['get_data']} return self.request(method, get_url, payload=data, cmd="get_%s" % key)
def get_boot_state(self): members = self._get_members(SYSTEMS_URL) target_url = members[0]['@odata.id'] data = self.request('GET', target_url, cmd='get_boot_state') try: boot_enable = data['Boot']['BootSourceOverrideEnabled'] if boot_enable == 'Disabled': return 'boot override inactive' bootsource = data['Boot']['BootSourceOverrideTarget'] return BOOTSOURCE_GET_STATE.get(bootsource, bootsource) except KeyError as e: raise SelfServerException('Get KeyError %s' % e.args)
def set_apis_values(self, key, value): attr_info = RSPCONFIG_APIS[key] if 'set_url' not in attr_info: raise SelfServerException("config %s failed, not url available" % key) set_url = attr_info['baseurl']+attr_info['set_url'] if 'attr_values' in attr_info and value in attr_info['attr_values']: data = attr_info['attr_values'][value] else: data = value method = 'PUT' if key == 'powersupplyredundancy': method = 'POST' self.request(method, set_url, payload={"data": data}, cmd="set_%s" % key)
def get_inventory_info(self, inventory_type): inventory_data = self.request('GET', INVENTORY_URLS[inventory_type], cmd='get_inventory_info') try: inventory_dict = {} if inventory_type == 'model' or inventory_type == 'serial': # The format of returned data for model and serial a different from other inventory types inventory_dict['SYSTEM'] = [] for key, value in inventory_data.items(): inventory_dict['SYSTEM'].append('%s %s : %s' % ("SYSTEM", key, value)) return inventory_dict for key, value in inventory_data.items(): if 'Present' not in value: logger.debug('Not "Present" for %s' % key) continue key_list = key.split('/') try: key_id = key_list[-1] key_tmp = key_list[-2] except IndexError: logger.debug('IndexError (-2) for %s' % key) continue key_type_list = [x for x in key_id if x not in '0123456789'] key_type = ''.join(key_type_list).upper() if key_type == 'CORE': key_type = 'CPU' source = '%s %s' % (key_tmp, key_id) else: source = key_id if key_type not in inventory_dict: inventory_dict[key_type] = [] for (sub_key, v) in value.items(): inventory_dict[key_type].append( '%s %s : %s' % (source.upper(), sub_key, v)) return inventory_dict except KeyError: error = 'Received wrong format response: %s' % inventory_data raise SelfServerException(error)
def handle_response(self, resp, cmd=''): code = resp.status_code if code == requests.codes.bad_gateway: error = "(Verify REST server is running on the BMC)" self._print_error_log(error, cmd) raise SelfServerException(code, error, host_and_port=self.bmcip) data = resp.json() # it will raise ValueError if code != requests.codes.ok: description = ''.join(data['data']['description']) error = '[%d] %s' % (code, description) self._print_error_log(error, cmd) raise SelfClientException(error, code) self._print_record_log(data['message'], cmd) return data['data']
def get_boot_state(self): state = self.request('GET', BOOTSOURCE_URLS['get']['path'], cmd='get_boot_state') try: one_time_path = PROJECT_URL + '/control/host0/boot/one_time' one_time_enabled = state[one_time_path]['Enabled'] if one_time_enabled: boot_source = state[one_time_path]['BootSource'].split('.')[-1] else: boot_source = state[PROJECT_URL + '/control/host0/boot']['BootSource'].split('.')[-1] error = 'Can not get valid rsetboot status, the data is %s' % boot_source boot_state = BOOTSOURCE_GET_STATE.get(boot_source.split('.')[-1], error) return boot_state except KeyError: error = 'Received wrong format response: %s' % states raise SelfServerException(error)
def handle_response(self, resp, cmd=''): data = resp.json() code = resp.status_code if code != requests.codes.ok and code != requests.codes.created: description = ''.join( data['error']['@Message.ExtendedInfo'][0]['Message']) error = '[%d] %s' % (code, description) self._print_error_log(error, cmd) raise SelfClientException(error, code) if cmd == 'login' and not 'X-Auth-Token' in resp.headers: raise SelfServerException( 'Login Failed: Did not get Session Token from response') self._print_record_log('%s %s' % (code, data['Name']), cmd) return data
def _get_power_actions(self): members = self._get_members(SYSTEMS_URL) target_url = members[0]['@odata.id'] data = self.request('GET', target_url, cmd='get_power_actions') try: actions_dict = data['Actions'][system_reset_string] target_url = actions_dict['target'] if reset_action_string in actions_dict: action_info = self.request('GET', actions_dict[reset_action_string], cmd='get_power_actions') actions = action_info['Parameters'][0]['AllowableValues'] else: actions = actions_dict[reset_type_string] except KeyError as e: raise SelfServerException('Get KeyError %s' % e.args) return (target_url, actions)
def get_inventory_info(self): inventory_data = self.request('GET', INVENTORY_URL, cmd='get_inventory_info') try: inverntory_dict = {} for key, value in inventory_data.items(): if 'Present' not in value: logger.debug('Not "Present" for %s' % key) continue key_list = key.split('/') try: key_id = key_list[-1] key_tmp = key_list[-2] except IndexError: logger.debug('IndexError (-2) for %s' % key) continue key_type = filter(lambda x: x not in '0123456789', key_id).upper() if key_type == 'CORE': key_type = 'CPU' source = '%s %s' % (key_tmp, key_id) else: source = key_id if key_type not in inverntory_dict: inverntory_dict[key_type] = [] for (sub_key, v) in value.items(): inverntory_dict[key_type].append( '%s %s : %s' % (source.upper(), sub_key, v)) return inverntory_dict except KeyError: error = 'Error: Received wrong format response: %s' % inventory_data raise SelfServerException(error)