def test09_add_management_server(self): print "**** Creating management server." usr = "" pwd = "" # find correct BMC passwords from global config for creds in fit_common.GLOBAL_CONFIG['credentials']['bmc']: if fit_common.remote_shell('ipmitool -I lanplus -H ' + fit_common.ARGS_LIST['bmc'] + ' -U ' + creds['username'] + ' -P ' + creds['password'] + ' fru')['exitcode'] == 0: usr = creds['username'] pwd = creds['password'] # create management node using these creds payload = { "name":"Management Server", "type": "mgmt", "autoDiscover": "true", "ipmi-obm-service": { "host": fit_common.ARGS_LIST['bmc'], "user": usr, "password": pwd } } api_data = fit_common.rackhdapi("/api/2.0/nodes", action='post', payload=payload) self.assertEqual(api_data['status'], 201, 'Incorrect HTTP return code, expecting 201, got ' + str(api_data['status'])) # run discovery workflow payload = { "name": "Graph.MgmtSKU.Discovery", "options":{"defaults": {"nodeId": api_data['json']['id']}} } api_data = fit_common.rackhdapi("/api/2.0/nodes/" + api_data['json']['id'] + "/workflows", action='post', payload=payload) self.assertEqual(api_data['status'], 201, 'Incorrect HTTP return code, expecting 201, got ' + str(api_data['status']))
def check_for_active_poller_data(self, max_time): ''' Determine if all poller have data. :param Time to wait (in 10 second intervals) :return: True - Poller have data False - Not all poller have data ''' poller_list = [] api_data = fit_common.rackhdapi('/api/2.0/pollers') if api_data: # set up a list of poller ids for index in api_data['json']: poller_list.append(index['id']) if poller_list != []: for _ in range(0, max_time): # move backwards through the list allowing completed poller ids to be popped # off the list for i in reversed(range(len(poller_list))): id = poller_list[i] poll_data = fit_common.rackhdapi("/api/2.0/pollers/" + id + "/data/current") # Check if data current returned 200 and data in the poll, if so, remove from list if poll_data['status'] == 200 and len(poll_data['json']) != 0: poller_list.pop(i) if poller_list == []: # return when all pollers look good return True time.sleep(10) if poller_list != []: log.error("Poller IDs with error or no data: {}".format(json.dumps(poller_list, indent=4))) return False
def test_api_20_templates_library_ID_put_get_delete(self): api_data = fit_common.rackhdapi("/api/2.0/templates/library/testid?scope=global", action="text-put", payload="null") self.assertEqual(api_data['status'], 201, "Was expecting code 201. Got " + str(api_data['status'])) api_data = fit_common.rackhdapi("/api/2.0/templates/library/testid") self.assertEqual(api_data['text'], "null", "Data 'null' was not returned.") self.assertEqual(api_data['status'], 200, "Was expecting code 200. Got " + str(api_data['status'])) api_data = fit_common.rackhdapi("/api/2.0/templates/library/testid", action="delete")
def test_redfish_v1_accountservice_accounts(self): api_data = fit_common.rackhdapi('/redfish/v1/AccountService/Accounts') self.assertEqual(api_data['status'], 200, "Was expecting code 200. Got " + str(api_data['status'])) #iterate through member links for item in api_data['json']['Members']: link_data = fit_common.rackhdapi(item['@odata.id']) self.assertEqual(link_data['status'], 200, "Was expecting code 200. Got " + str(link_data['status']))
def test_04_redfish_v1_chassis_id_thermal(self): errorlist = [] # Get list of Chassis from the stack api_data = fit_common.rackhdapi('/redfish/v1/Chassis') self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code') for nodeid in api_data['json']['Members']: thermalurl = nodeid['@odata.id'] + "/Thermal" node = nodeid['@odata.id'].split('/')[-1] if fit_common.VERBOSITY >= 2: print ("Node ID: {} ".format(node)) print "Thermal url", thermalurl api_data = fit_common.rackhdapi(thermalurl) if api_data['status'] != 200: errorlist.append("Nodeid: {} Bad return code {} for url: {}".format(node, api_data['status'], thermalurl)) else: for item in ['@odata.type', '@odata.id', 'Id']: if fit_common.VERBOSITY >= 2: print ("Checking: {0}".format(item)) self.assertIn(item, api_data['json'], item + ' field not present') if fit_common.VERBOSITY >= 3: print ("\t {0}".format( api_data['json'][item])) self.assertGreater(len(api_data['json'][item]), 0, item + ' field empty') if errorlist: print json.dumps(errorlist, indent=4) self.assertEqual(errorlist, [], "Errors found".format(errorlist))
def test_02_redfish_v1_chassis_id_links(self): #iterate through list of chassis from redfish api_data = fit_common.rackhdapi('/redfish/v1/Chassis') self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code') for nodeid in api_data['json']['Members']: if fit_common.VERBOSITY >= 2: print ("Node ID: {} ".format(nodeid)) api_data = fit_common.rackhdapi(nodeid['@odata.id']) self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) # check required fields # check Name field first because that will be used for other checks self.assertIn('Name', api_data['json'], 'Name field not present') self.assertGreater(len(api_data['json']['Name']), 0, 'Name field empty') chassis_name = api_data['json']['Name'] if fit_common.VERBOSITY >= 2: print ("Node ID: {} Name: {} ".format(nodeid, chassis_name)) for item in ['Links', '@odata.id', '@odata.type']: if fit_common.VERBOSITY >= 2: print ("Checking: {0}".format(item)) self.assertIn(item, api_data['json'], item + ' field not present') # if the chassis name is Unknown, fields will not be populated if chassis_name != 'Unknown': if fit_common.VERBOSITY >= 2: print ("Chassis_name : {0}".format(chassis_name)) print ("Checking: {0}".format(item)) self.assertGreater(len(api_data['json'][item]), 0, item + ' field empty')
def test_7_poller_error_counter(self): msg = "Description: Check for Poller Errors" if fit_common.VERBOSITY >= 2: print "\t{0}".format(msg) errorlist = [] for node in NODELIST: if fit_common.VERBOSITY >= 2: nodetype = get_rackhd_nodetype(node) print "\nNode: {} Type: {}".format(node, nodetype) mondata = fit_common.rackhdapi("/api/2.0/nodes/" + node + "/pollers") self.assertIn(mondata['status'], [200], "Incorrect HTTP return code, expecting 200, received {}".format(mondata['status'])) for item in mondata['json']: # check required fields if item['pollInterval'] == 0: errorlist.append("Node: {} pollInterval field error: {}".format(node, item['pollInterval'])) for subitem in ['node', 'config', 'createdAt', 'id', 'name', 'config', 'updatedAt']: if subitem not in item: errorlist.append("Node: {} field error: {}".format(node, subitem)) poller_dict = test_api_utils.get_supported_pollers(node) for poller in poller_dict: poller_id = poller_dict[poller]["poller_id"] poll_data = fit_common.rackhdapi("/api/2.0/pollers/" + poller_id) poll_fails = poll_data['json'].get('failureCount', 0) if poll_fails != 0: errorlist.append("Node: {} Poller: {} {} reported {} failureCount".format(node, poller, poller_id, poll_fails)) if errorlist != []: print "{}".format(fit_common.json.dumps(errorlist, indent=4)) self.assertEqual(errorlist, [], "Error reported in Pollers counters") else: if fit_common.VERBOSITY >= 2: print "No Poller errors found"
def check_for_active_workflows(self, max_time): ''' Determine if are any active workflows. :param Time to wait (in 10 second intervals) :return: True - No active workflows False - Workflows are active ''' for dummy in range(0, max_time): nodes_data = fit_common.rackhdapi("/api/2.0/nodes") if nodes_data['status'] == 200 and len(nodes_data['json']) > 0: # if there are nodes present, determine if discovery has completed on them discovery_complete = True for node in nodes_data['json']: if node['type'] == 'compute': self.assertIn('id', node, 'node does not contain id') node_id = node['id'] # determine if there are any active worlflows. If so, discovery not completed awf_data = fit_common.rackhdapi('/api/1.1/nodes/' + node_id + '/workflows/active') # 204 indicates "No Content" if awf_data['status'] != 204 or 'sku' not in node: discovery_complete = False break if discovery_complete: return True fit_common.time.sleep(10) return False
def test_redfish_v1_systems_id_logservices(self): # iterate through node IDs for nodeid in NODECATALOG: api_data = fit_common.rackhdapi('/redfish/v1/Systems/' + nodeid) if api_data['status'] == 200: api_data = fit_common.rackhdapi('/redfish/v1/Systems/' + nodeid + '/LogServices') self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status']))
def test_verify_poller_error_counter(self): msg = "Description: Check for Poller Errors" print "\t{0}".format(msg) errorlist = [] for node in NODELIST: mon_data = fit_common.rackhdapi("/api/1.1/nodes/" + node + "/pollers") self.assertIn(mon_data['status'], [200], "Incorrect HTTP return code") for item in mon_data['json']: # check required fields self.assertGreater(item['pollInterval'], 0, 'pollInterval field error') for subitem in ['node', 'config', 'createdAt', 'id', 'name', 'config', 'updatedAt']: self.assertIn(subitem, item, subitem + ' field error') poller_dict = test_api_utils.get_supported_pollers(node) for poller in poller_dict: poller_id = poller_dict[poller]["poller_id"] poll_data = fit_common.rackhdapi("/api/1.1/pollers/" + poller_id) poll_fails = poll_data['json'].get('failureCount', 0) if poll_fails != 0: errorlist.append("Node: {} Poller: {} {} reported {} failureCount".format(node, poller, poller_id, poll_fails)) if errorlist != []: print "{}".format(fit_common.json.dumps(errorlist, indent=4)) self.assertEqual(errorlist, [], "Error reported in Pollers") else: if fit_common.VERBOSITY >- 2: print ("No Poller errors found")
def __apply_obmsetting_to_node(self, nodeid): usr = None # pwd = '' response = fit_common.rackhdapi( '/api/2.0/nodes/' + nodeid + '/catalogs/bmc') bmcip = response['json']['data']['IP Address'] # Try credential record in config file for creds in fit_common.fitcreds()['bmc']: if fit_common.remote_shell( 'ipmitool -I lanplus -H ' + bmcip + ' -U ' + creds['username'] + ' -P ' + creds['password'] + ' fru')['exitcode'] == 0: usr = creds['username'] pwd = creds['password'] break # Put the credential to OBM settings if usr is not None: payload = { "service": "ipmi-obm-service", "config": { "host": bmcip, "user": usr, "password": pwd}, "nodeId": nodeid} api_data = fit_common.rackhdapi("/api/2.0/obms", action='put', payload=payload) if api_data['status'] == 201: return True return False
def test_nodes_id_pollers(self): msg = "Description: Display the poller updated-at per node." print "\t{0}".format(msg) node = 0 errorlist = [] for node in NODELIST: if fit_common.VERBOSITY >= 2: print "Node: {}".format(node) mondata = fit_common.rackhdapi("/api/1.1/nodes/" + node + "/pollers") self.assertIn(mondata['status'], [200], "Incorrect HTTP return code, expecting 200, received {}".format(mondata['status'])) for item in mondata['json']: # check required fields if item['pollInterval'] == 0: errorlist.append("Node: {} pollInterval field error: {}".format(node, item['pollInterval'])) for subitem in ['node', 'config', 'createdAt', 'id', 'name', 'config', 'updatedAt']: if subitem not in item: errorlist.append("Node: {} field error: {}".format(node, subitem)) poller_dict = test_api_utils.get_supported_pollers(node) for poller in poller_dict: poller_id = poller_dict[poller]["poller_id"] poll_data = fit_common.rackhdapi("/api/1.1/pollers/" + poller_id) if fit_common.VERBOSITY >= 2: print "\nPoller: {} ID: {} ".format(poller, str(poller_id)) print "Created At: {}".format(fit_common.json.dumps(poll_data['json']['createdAt'])) print "Updated At: {}".format(fit_common.json.dumps(poll_data['json']['updatedAt'])) if errorlist != []: print "{}".format(fit_common.json.dumps(errorlist, indent=4)) self.assertEqual(errorlist, [], "Error reporterd.")
def test_redfish_v1_eventservice_subscriptions_post_get_delete(self): payload = { "@odata.context": "string", "@odata.id": str(fit_common.time.time()), "@odata.type": str(fit_common.time.time()), "Context": "Test", "Description": str(fit_common.time.time()), "Destination": str(fit_common.time.time()), "EventTypes": [ "StatusChange" ], "HttpHeaders": [ {} ], "Id": str(fit_common.time.time()), "Name": str(fit_common.time.time()), "Oem": {}, "Protocol": "Redfish" } api_data = fit_common.rackhdapi('/redfish/v1/EventService/Subscriptions', action="post", payload=payload) self.assertEqual(api_data['status'], 201, "Was expecting code 201. Got " + str(api_data['status'])) api_data = fit_common.rackhdapi('/redfish/v1/EventService/Subscriptions/' + api_data['json']['Id']) self.assertEqual(api_data['status'], 200, "Was expecting code 200. Got " + str(api_data['status'])) api_data = fit_common.rackhdapi('/redfish/v1/EventService/Subscriptions/' + api_data['json']['Id'], action="delete") self.assertEqual(api_data['status'], 200, "Was expecting code 200. Got " + str(api_data['status']))
def setUpClass(cls): # Get the list of nodes NODECATALOG = fit_common.node_select() assert (len(NODECATALOG) != 0), "There are no nodes currently discovered" # Select one node at random cls.__NODE = NODECATALOG[random.randint(0, len(NODECATALOG) - 1)] # Print node Id, node BMC mac ,node type nodeinfo = fit_common.rackhdapi('/api/2.0/nodes/' + cls.__NODE)['json'] nodesku = fit_common.rackhdapi(nodeinfo.get('sku'))['json']['name'] monurl = "/api/2.0/nodes/" + cls.__NODE + "/catalogs/bmc" mondata = fit_common.rackhdapi(monurl, action="get") catalog = mondata['json'] bmcresult = mondata['status'] if bmcresult != 200: log.info_1(" Node ID: " + cls.__NODE) log.info_1(" Error on catalog/bmc command") else: log.info_1(" Node ID: " + cls.__NODE) log.info_1(" Node SKU: " + nodesku) log.info_1(" Node BMC Mac: %s", catalog.get('data')['MAC Address']) log.info_1(" Node BMC IP Addr: %s", catalog.get('data')['IP Address']) log.info_1(" Node BMC IP Addr Src: %s", catalog.get('data')['IP Address Source']) # delete active workflows for specified node result = fit_common.cancel_active_workflows(cls.__NODE) assert (result is True), "There are still some active workflows running against the node"
def test_api_11_obms_library(self): api_data = fit_common.rackhdapi("/api/1.1/obms/library") self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) for item in api_data['json']: obm_data = fit_common.rackhdapi("/api/1.1/obms/library/" + item['service']) self.assertEqual(obm_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) self.assertGreater(len(obm_data['json']['service']), 0, 'service field error')
def test_api_11_pollers_post_delete(self): mon_ip_addr = "172.31.128.200" poller_id = fit_common.rackhdapi("/api/1.1/nodes/" + MON_NODES[0])['json']['id'] data_payload = {"name": "test", "type": "ipmi", "ip": str(mon_ip_addr), "user": "******", "password": "******", "node": str(poller_id), "pollInterval": 100, "config":{"command":"sdr"}} # Create a new SDR poller, should return status 200 api_data = fit_common.rackhdapi('/api/1.1/pollers/', action="post", payload=data_payload) self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) # Check that the new poller shows up in the GET mon_url = "/api/1.1/pollers/" + api_data['json']["id"] api_data = fit_common.rackhdapi(mon_url) self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) # Delete the new poller, should return status 204 api_data = fit_common.rackhdapi(mon_url, action="delete") self.assertEqual(api_data['status'], 204, 'Incorrect HTTP return code, expected 204, got:' + str(api_data['status'])) # Check that the poller can no longer be retrieved (404 Not Found) api_data = fit_common.rackhdapi(mon_url) self.assertEqual(api_data['status'], 404, 'Incorrect HTTP return code, expected 404, got:' + str(api_data['status']))
def test_2_pollers_by_id(self): msg = "Description: Display the poller data per node." if fit_common.VERBOSITY >= 2: print "\t{0}".format(msg) errorlist = [] poller_list = ['driveHealth', 'sel', 'chassis', 'selInformation', 'sdr'] for node in NODELIST: if fit_common.VERBOSITY >= 2: nodetype = get_rackhd_nodetype(node) print "Node: {} Type: {}".format(node, nodetype) mondata = fit_common.rackhdapi("/api/2.0/nodes/" + node + "/pollers") self.assertIn(mondata['status'], [200], "Incorrect HTTP return code, expecting 200, received {}".format(mondata['status'])) # check required fields for item in mondata['json']: if item['pollInterval'] == 0: errorlist.append("Node: {} pollInterval field error: {}".format(node, item['pollInterval'])) for subitem in ['node', 'config', 'createdAt', 'id', 'name', 'config']: if subitem not in item: errorlist.append("Node: {} field error: {}".format(node, subitem)) # display poller data for the node poller_dict = test_api_utils.get_supported_pollers(node) for poller in poller_dict: poller_id = poller_dict[poller]["poller_id"] if fit_common.VERBOSITY >= 2: print "Poller: {} ID: {} ".format(poller, str(poller_id)) poll_data = fit_common.rackhdapi("/api/2.0/pollers/" + poller_id) if fit_common.VERBOSITY >= 3: print fit_common.json.dumps(poll_data.get('json', ""), indent=4) if errorlist != []: print "{}".format(fit_common.json.dumps(errorlist, indent=4)) self.assertEqual(errorlist, [], "Error reported.")
def test_check_poller_interval(self): msg = "Description: Display the poller interval." print "\t{0}".format(msg) for node in NODELIST: print "\nNode: ", node mon_data = fit_common.rackhdapi("/api/1.1/nodes/" + node + "/pollers") self.assertIn(mon_data['status'], [200], "Incorrect HTTP return code, expected 200, got {}".format(mon_data['status'])) poller_list = [] print "mon_data " print fit_common.json.dumps(mon_data['json'], indent=4) for item in mon_data['json']: poller_list.append(item['id']) print "Poller list", poller_list for poller_id in poller_list: poller = fit_common.rackhdapi("/api/1.1/pollers/" + poller_id ) self.assertIn(poller['status'], [200], "Incorrect HTTP return code") pollerdata = poller['json'] # check required fields self.assertGreater(pollerdata['pollInterval'], 0, 'pollInterval field error') poller_interval = pollerdata['pollInterval'] print "pollerInterval", poller_interval pollertime = poller_interval / 1000 print pollerdata['config'].get('metric', "") print pollerdata.get('nextScheduled', "") print pollertime pollcurrent = fit_common.rackhdapi("/api/1.1/pollers/" + poller_id + "/data/current" ) self.assertIn(pollcurrent['status'], [200], "Incorrect HTTP return code") if fit_common.VERBOSITY >= 2: print fit_common.json.dumps(pollcurrent, indent=4)
def test_sel_alert(self): # The SEL log poller test will inject a CPU IERR event in the node BMC and moniter the AMQP message queue node_collection = test_api_utils.get_node_list_by_type("compute") nodeid = "" # Check is skupack is installed. If no skupack installed, we won't get any SEL alert if self.check_skupack() is False: self.fail("No skupack is intalled in the RackHD. The SEL alert test will fail.") for dummy in node_collection: nodeid = node_collection[random.randint(0, len(node_collection) - 1)] if fit_common.rackhdapi('/api/2.0/nodes/' + nodeid)['json']['name'] != "Management Server": break logs.debug_2('Checking OBM setting...') node_obm = fit_common.rackhdapi( '/api/2.0/nodes/' + nodeid)['json']['obms'] if node_obm == []: self.assertTrue(self._apply_obmsetting_to_node(nodeid), "Fail to apply obm setting!") # Clear sel to avoid the sel log full test_api_utils.run_ipmi_command_to_node(nodeid, "sel clear") # Find the SEL poller id. This id will be used to validate AMQP message body. pollerid = self._get_ipmi_poller_by_node(nodeid, "selEntries") logs.debug('launch AMQP thread for sel alert') sel_worker = AmqpWorker( exchange_name="on.events", topic_routing_key="polleralert.sel.#." + nodeid, external_callback=self.amqp_callback, timeout=200) sel_worker.setDaemon(True) sel_worker.start() # Send out sel iERR injection. command = "raw 0x0a 0x44 0x01 0x00 0x02 0xab 0xcd 0xef 0x00 0x01 0x00 0x04 0x07 0x02 0xef 0x00 0x00 0x00" test_api_utils.run_ipmi_command_to_node(nodeid, command) self._wait_amqp_message(200) workflow_amqp = amqp_queue.get() self._process_message("sel.updated", pollerid, nodeid, "polleralert", "critical", workflow_amqp) sel_worker.dispose()
def get_compute_node_username(node_id): """ Get the username credential from node id :param node_id: The id given by OnRack :return: dict_credential = {"user": user_name, "password": password} 1 on network error 2 on parsing error 3 on unable to obtain password from username 4 Get compute node credentials failure Otherwise """ monorail_url = "/api/2.0/nodes/" + node_id rest_res = {'json': "", 'text': "", 'status': "", 'headers': ""} rest_res = fit_common.rackhdapi(url_cmd=monorail_url) if rest_res['status'] != 200: if fit_common.VERBOSITY >= 2: print "Error in getting response with url\n\t" + monorail_url return 1 node_info = rest_res['json'] try: obm_list = node_info['obms'] obm_url = obm_list[0]['ref'] obm_data = fit_common.rackhdapi(obm_url, action="get") if obm_data['status'] != 200: if fit_common.VERBOSITY >= 2: print "Error in getting response with obm data\n\t" + obm_url return 1 username = obm_data['json']['config'].get('user') if username: user = unicodedata.normalize('NFKD', username).encode('ascii', 'ignore') else: if fit_common.VERBOSITY >= 2: print "Unable to obtain the user name from node id given" return 2 if user: password = guess_the_password(user) else: if fit_common.VERBOSITY >= 2: print "Unable to obtain the user name from test host and node id" return 2 if password is None: if fit_common.VERBOSITY >= 2: print "Unable to obtain the password from test host and node id" return 3 ret_dict_cred = {"user": user, "password": password} return ret_dict_cred except: if fit_common.VERBOSITY >= 2: print "ERROR: Get compute node credentials failed" return 4
def test_api_20_obms_definitions(self): api_data = fit_common.rackhdapi("/api/2.0/obms/definitions") self.assertEqual( api_data["status"], 200, "Incorrect HTTP return code, expected 200, got:" + str(api_data["status"]) ) # check links for item in api_data["json"]: self.assertEqual(fit_common.rackhdapi(item)["status"], 200, "Bad link: " + item)
def test_api_11_schemas(self): api_data = fit_common.rackhdapi("/api/1.1/schemas") self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) for item in api_data['json']: if fit_common.VERBOSITY >= 2: print "Checking:", item['id'] self.assertEqual(fit_common.rackhdapi("/api/1.1/schemas/" + item['id']) ['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status']))
def test_api_20_nodes_ID_ssh(self): # iterate through nodes for nodeid in NODECATALOG: payload = {"service": "ssh-ibm-service", "config": {"host": "1.1.1.1", "user": "******", "password": "******"}} api_data = fit_common.rackhdapi("/api/2.0/nodes/" + nodeid + "/ssh", action="post", payload=payload) self.assertEqual(api_data['status'], 201, 'Incorrect HTTP return code, expected 201, got:' + str(api_data['status'])) api_data = fit_common.rackhdapi("/api/2.0/nodes/" + nodeid + "/ssh") self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status']))
def test_api_11_nodes_ID_catalogs_source(self): # iterate through sources api_data = fit_common.rackhdapi('/api/1.1/catalogs') for sourceid in api_data['json']: # iterate through nodes for nodeid in MON_NODES: api_data = fit_common.rackhdapi("/api/1.1/nodes/" + nodeid + "/catalogs/" + sourceid['source']) self.assertIn(api_data['status'], [200, 404], 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status']))
def test_poller_bandwidth_util(self): msg = "Description: Display snmp-interface-bandwidth-utilization." print "\t{0}".format(msg) for node in NODELIST: print "\nNode: ", node item_polls = {} mon_data = fit_common.rackhdapi("/api/2.0/nodes/" + node + "/pollers") self.assertIn(mon_data['status'], [200], "Incorrect HTTP return code, expected 200, got {}".format(mon_data['status'])) poller_list = [] poller_test = "snmp-interface-bandwidth-utilization" for item in mon_data['json']: if item['config']['metric'] == poller_test: poller_list.append(item['id']) print "Poller list", poller_list self.assertNotEquals(poller_list, [], "Poller {0} not in list of pollers".format(poller_test)) pollertime = i = 0 while i < POLLS: if POLLS > 1 and pollertime: print "sleeping " + str(pollertime) + " seconds" time.sleep(pollertime) # for the list of poller ids, get the poller data and check the fields exist for poller_id in poller_list: poller = fit_common.rackhdapi("/api/2.0/pollers/"+ poller_id) self.assertIn(poller['status'], [200], "Incorrect HTTP return code, expected 200, got {}".format(poller['status'])) pollerdata = poller['json'] item_polls = {'node': node, 'poller': pollerdata['config']['metric'], "next_poll": pollerdata['nextScheduled']} # check required fields and grab the poller times self.assertGreater(pollerdata['pollInterval'], 0, 'pollInterval field error') poller_interval = pollerdata['pollInterval'] print "pollerInterval", poller_interval pollertime = poller_interval / 1000 # metric is the name of the poller print "PollerData metric: ", pollerdata['config']['metric'] print "NextScheduled poll: ", pollerdata['nextScheduled'] print "PollerTime: ", pollertime # get the current readings from the switch for this poller pollcurrent = fit_common.rackhdapi("/api/2.0/pollers/"+ poller_id + "/data/current") self.assertIn(pollcurrent['status'], [200], "Incorrect HTTP return code, expected 200, got {}".format(pollcurrent['status'])) # dump the world if fit_common.VERBOSITY >= 3: print json.dumps(pollcurrent['json'], indent=4) # display the interfaces that are UP if fit_common.VERBOSITY >= 2: result = pollcurrent['json'][0]['result'] for key, value in result.items(): if value.get("inputUtilization") != None: print "IF: {} Utilization: {}".format(key, value) i += 1
def test03_upload_sku_packs(self): # upload SKU packs to RackHD for subdir, dirs, files in os.walk('on-skupack/tarballs'): for skupacks in files: print "\n**** Loading SKU Pack for " + skupacks fit_common.rackhdapi("/api/2.0/skus/pack", action="binary-post", payload=file(fit_common.TEST_PATH + "on-skupack/tarballs/" + skupacks).read()) break print "\n"
def setUp(self): # create test file TESTFILE = open(fit_common.TEST_PATH + "testfile", "w+") TESTFILE.write("1234567890ABCDEF") TESTFILE.close() # delete any instance of testfile on host api_data = fit_common.rackhdapi("/api/2.0/files") for item in api_data["json"]: if item["filename"] == "testfile": fit_common.rackhdapi("/api/2.0/files/" + item["uuid"], action="delete")
def test_api_11_nodes_ID_tags(self): # iterate through nodes for nodeid in MON_NODES: #add tag api_data = fit_common.rackhdapi("/api/1.1/nodes/" + nodeid + "/tags", action="patch", payload={"tags":["test_tag_" + nodeid]}) self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) #check tag api_data = fit_common.rackhdapi("/api/1.1/nodes/" + nodeid + "/tags") self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) self.assertIn("test_tag_" + nodeid, fit_common.json.dumps(api_data['json']), "Tag not set:" + fit_common.json.dumps(api_data['json']))
def test_api_11_templates_library_ID_put_get_delete(self): # this test creates a dummy template called 'testid', checks it, then deletes it api_data = fit_common.rackhdapi("/api/1.1/templates/library/testid?scope=global", action="text-put", payload="null") self.assertEqual(api_data['status'], 200, "Was expecting code 200. Got " + str(api_data['status'])) api_data = fit_common.rackhdapi("/api/1.1/templates/library/testid") self.assertIn(api_data['json']['contents'], "null", "Data 'null' was not returned.") self.assertEqual(api_data['status'], 200, "Was expecting code 200. Got " + str(api_data['status'])) # template 'delete' not supported in API 1.1, using 2.0 api_data = fit_common.rackhdapi("/api/2.0/templates/library/testid", action="delete") self.assertEqual(api_data['status'], 200, "Was expecting code 200. Got " + str(api_data['status']))
def setUp(self): # create test file TESTFILE = open(fit_common.TEST_PATH + 'testfile','w+') TESTFILE.write("1234567890ABCDEF") TESTFILE.close() # delete any instance of testfile on host api_data = fit_common.rackhdapi('/api/2.0/files') for item in api_data['json']: if item['filename'] == 'testfile': fit_common.rackhdapi('/api/2.0/files/' + item['uuid'], action="delete")
def test_api_20_nodes_ID_workflows(self): # iterate through nodes for nodeid in NODECATALOG: api_data = fit_common.rackhdapi("/api/2.0/nodes/" + nodeid + "/workflows") self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) for item in api_data['json']: # check required fields for subitem in ['createdAt', 'context', 'definition']: if fit_common.VERBOSITY >= 2: print "Checking:", item['name'], subitem self.assertIn(subitem, item, subitem + ' field error')
def test07_discover_pdu_node(self): log.info_5("**** Creating PDU node.") payload = {"type": "pdu", "name": "PDU", "autoDiscover": "true", "obms": [{"service": "snmp", "config": {"host": fit_common.fitcfg()['pdu'], "community": fit_common.fitcreds()['snmp'][0]['community']}}]} api_data = fit_common.rackhdapi("/api/2.0/nodes/", action='post', payload=payload) self.assertEqual(api_data['status'], 201, 'Incorrect HTTP return code, expecting 201, got ' + str(api_data['status']))
def test_api_20_nodes_ID_obmsettings(self): # create fake node data_payload = {"name": "fakenode", "type": "compute"} api_data = fit_common.rackhdapi("/api/2.0/nodes", action="post", payload=data_payload) self.assertEqual(api_data['status'], 201, 'Incorrect HTTP return code, expected 201, got:' + str(api_data['status'])) obm_id = api_data['json']['id'] # assign OBM data_payload = {'obmSettings': [ {'service': 'ipmi-obm-service', 'config': {'user': '******', 'password': '******', 'host': '172.31.128.100'}}]} mon_url = "/api/2.0/nodes/" + obm_id api_data = fit_common.rackhdapi(mon_url, action="patch", payload=data_payload) self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) # delete node api_data = fit_common.rackhdapi(mon_url, action="delete") self.assertEqual(api_data['status'], 204, 'Incorrect HTTP return code, expected 204, got:' + str(api_data['status'])) api_data = fit_common.rackhdapi(mon_url) self.assertEqual(api_data['status'], 404, 'Incorrect HTTP return code, expected 404, got:' + str(api_data['status']))
def test_redfish_v1_systems_id_logservices_sel_entries_id(self): # iterate through node IDs for nodeid in NODECATALOG: api_data = fit_common.rackhdapi("/redfish/v1/Systems/" + nodeid + "/LogServices/SEL/Entries") if fit_common.VERBOSITY >= 2: print ("nodeid: {0}".format(nodeid)) self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) for member in api_data['json']['Members']: self.assertIn('@odata.id', member, '@odata.id field not present') self.assertGreater(len(member['@odata.id']), 0, '@odata.id field empty') if fit_common.VERBOSITY >= 2: print ("\nEntry {0}".format(member['@odata.id'])) #get the selid off the list selid = str(member['Id']) if fit_common.VERBOSITY >= 3: print ("SEL Entry: {0}".format(selid)) #retrieve the data for the specific SEL entry and iterate through individual fields seldata = fit_common.rackhdapi("/redfish/v1/Systems/" + nodeid + "/LogServices/SEL/Entries/" + selid) self.assertEqual(seldata['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(seldata['status'])) for item in [ 'Id', 'Created', 'EntryCode', 'EntryType', 'SensorType', 'Name', 'Message' ]: if fit_common.VERBOSITY >= 2: print ("Checking: {0}".format(item)) if item == 'Created' and item not in seldata['json']: log.info_5("Created field does not exist for SEL Sensor Type:" + seldata['json']['SensorType'] + " SensorNumber:" + str(seldata['json']['SensorNumber'])) else: self.assertIn(item, seldata['json'], item + ' field not present') if fit_common.VERBOSITY >= 3: print("\t {0}".format(seldata['json'][item])) if len(seldata['json'][item]) == 0 and item == 'Message': log.info_5("Message field empty for SEL SensorType:" + seldata['json']['SensorType'] + " SensorNumber:" + str(seldata['json']['SensorNumber'])) elif len(seldata['json'][item]) == 0 and item == 'Created': log.info_5("Created field empty for SEL SensorType:" + seldata['json']['SensorType'] + " SensorNumber:" + str(seldata['json']['SensorNumber'])) else: self.assertGreater(len(seldata['json'][item]), 0, item + ' field empty')
def test_sel_alert(self): # The SEL log poller test will inject a CPU IERR event in the node BMC and moniter the AMQP message queue node_collection = test_api_utils.get_node_list_by_type("compute") nodeid = "" # Check is skupack is installed. If no skupack installed, we won't get any SEL alert if self.check_skupack() is False: self.fail( "No skupack is intalled in the RackHD. The SEL alert test will fail." ) for dummy in node_collection: nodeid = node_collection[random.randint(0, len(node_collection) - 1)] if fit_common.rackhdapi('/api/2.0/nodes/' + nodeid )['json']['name'] != "Management Server": break logs.debug_2('Checking OBM setting...') node_obm = fit_common.rackhdapi('/api/2.0/nodes/' + nodeid)['json']['obms'] if node_obm == []: self.assertTrue(self._apply_obmsetting_to_node(nodeid), "Fail to apply obm setting!") # Clear sel to avoid the sel log full test_api_utils.run_ipmi_command_to_node(nodeid, "sel clear") # Find the SEL poller id. This id will be used to validate AMQP message body. pollerid = self._get_ipmi_poller_by_node(nodeid, "selEntries") logs.debug('launch AMQP thread for sel alert') sel_worker = AmqpWorker(exchange_name="on.events", topic_routing_key="polleralert.sel.#." + nodeid, external_callback=self.amqp_callback, timeout=200) sel_worker.setDaemon(True) sel_worker.start() # Send out sel iERR injection. command = "raw 0x0a 0x44 0x01 0x00 0x02 0xab 0xcd 0xef 0x00 0x01 0x00 0x04 0x07 0x02 0xef 0x00 0x00 0x00" test_api_utils.run_ipmi_command_to_node(nodeid, command) self._wait_amqp_message(200) workflow_amqp = amqp_queue.get() self._process_message("sel.updated", pollerid, nodeid, "polleralert", "critical", workflow_amqp) sel_worker.dispose()
def test_api_11_config_httpendpoints(self): api_data = fit_common.rackhdapi('/api/1.1/config') self.assertEqual(api_data['status'], 200, "Was expecting code 200. Got " + str(api_data['status'])) self.assertIn('httpEndpoints', api_data['json'], 'httpEndpoints field list error') # verify both northbound and southbound endpoints are configured (as a minimum) for endpoint in api_data['json']['httpEndpoints']: self.assertIn('address', endpoint, 'missing httpEndpoints address field') self.assertIn('authEnabled', endpoint, 'missing httpEndpoints authEnabled field') self.assertIn('httpsEnabled', endpoint, 'missing httpEndpoints httpsEnabled field') self.assertIn('proxiesEnabled', endpoint, 'missing httpEndpoints proxiesEnabled field') self.assertIn('routers', endpoint, 'missing httpEndpoints routers field') self.assertIn(endpoint['routers'], ['northbound-api-router', 'southbound-api-router'], 'unexpected httpEndpoints routers field')
def test_redfish_v1_managers_rackhd_ethernetinterfaces(self): api_data = fit_common.rackhdapi( '/redfish/v1/Managers/RackHD/EthernetInterfaces') self.assertEqual( api_data['status'], 200, "Was expecting code 200. Got " + str(api_data['status'])) #iterate through member links for item in api_data['json']['Members']: manager_data = fit_common.rackhdapi(item['@odata.id']) self.assertEqual( manager_data['status'], 200, "Was expecting code 200. Got " + str(manager_data['status'])) # if configured, test IP addresses of each port if 'IPv4Addresses' in manager_data[ 'json'] and 'Address' in manager_data['json'][ 'IPv4Addresses']: for item in manager_data['json']['IPv4Addresses']: self.assertEqual( fit_common.remote_shell('ping -c 1 ' + item["Address"])['exitcode'], 0, "Manager IP address not found.")
def get_node_list_by_type(node_type): """ Get node list according to type (like PDU, compute) :param type: :return: node id list for given type """ node_info = fit_common.rackhdapi(url_cmd="/api/2.0/nodes?type=" + node_type) node_list = [] if node_info["status"] in [200, 201, 202, 204]: for node in node_info["json"]: node_list.append(node["id"]) return node_list
def get_rackhd_nodetype(nodeid): nodetype = "unknown" sku = "" # get node info mondata = fit_common.rackhdapi("/api/2.0/nodes/" + nodeid) if mondata['status'] == 200: # get the sku id contained in the node sku = mondata['json'].get("sku") if sku: skudata = fit_common.rackhdapi(sku) if skudata['status'] == 200: nodetype = skudata['json'].get("name") else: if fit_common.VERBOSITY >= 2: errmsg = "Error: SKU API failed {}, return code {} ".format(sku, skudata['status']) print errmsg else: if fit_common.VERBOSITY >= 2: errmsg = "Error: nodeid {} did not return a valid sku in get_rackhd_nodetype {}".format(nodeid, sku) print errmsg return nodetype
def test_api_11_templates_library_ID_put_get_delete(self): # this test creates a dummy template called 'testid', checks it, then deletes it api_data = fit_common.rackhdapi( "/api/1.1/templates/library/testid?scope=global", action="text-put", payload="null") self.assertEqual( api_data['status'], 200, "Was expecting code 200. Got " + str(api_data['status'])) api_data = fit_common.rackhdapi("/api/1.1/templates/library/testid") self.assertIn(api_data['json']['contents'], "null", "Data 'null' was not returned.") self.assertEqual( api_data['status'], 200, "Was expecting code 200. Got " + str(api_data['status'])) # template 'delete' not supported in API 1.1, using 2.0 api_data = fit_common.rackhdapi("/api/2.0/templates/library/testid", action="delete") self.assertEqual( api_data['status'], 200, "Was expecting code 200. Got " + str(api_data['status']))
def test_api_11_nodes_ID_pollers(self): # iterate through nodes for nodeid in NODECATALOG: api_data = fit_common.rackhdapi("/api/1.1/nodes/" + nodeid + "/pollers") self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) for item in api_data['json']: # check required fields self.assertGreater(item['pollInterval'], 0, 'pollInterval field error') for subitem in ['node', 'config', 'createdAt', 'id', 'name']: if fit_common.VERBOSITY >= 2: print "Checking:", item['name'], subitem self.assertIn(subitem, item, subitem + ' field error')
def delete_nodes_by_type(node_type): ''' Delete all nodes for a given node_type :param node_type: :return: ''' node_list = [] node_list = get_node_list_by_type(node_type) if node_list == []: return 0 for node_id in node_list: active_wf = get_active_workflow(node_id) if active_wf != 0: delete_active_workflow(node_id) fit_common.rackhdapi(url_cmd="/api/1.1/nodes/" + node_id, action="delete") node_list = get_node_list_by_type(node_type) if node_list == []: return 0 else: return -1
def test02_preload_default_sku(self): # Load default SKU for unsupported compute nodes print '**** Installing default SKU' payload = { "name": "Unsupported-Compute", "rules": [{ "path": "bmc.IP Address" }] } api_data = fit_common.rackhdapi("/api/2.0/skus", action='post', payload=payload)
def test_api_20_pollers_duplicates(self): api_data = fit_common.rackhdapi('/api/2.0/pollers/library') for item in api_data['json']: poll_data = fit_common.rackhdapi('/api/2.0/pollers/library/' + item['name']) self.assertEqual( poll_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) self.assertGreater(len(item['name']), 0, 'name field error') self.assertGreater(len(item['config']), 0, 'config field error') # duplicate check nodelist = api_data['json'] for nodenum in range(1, len(api_data['json'])): # poller library name for nodecheck in range(0, len(api_data['json'])): if nodenum != nodecheck: self.assertNotEqual( nodelist[nodenum]['name'], nodelist[nodecheck]['name'], "Duplicate poller lib name " + nodelist[nodenum]['name'])
def test_api_20_config(self): api_data = fit_common.rackhdapi('/api/2.0/config') self.assertEqual(api_data['status'], 200, "Was expecting code 200. Got " + str(api_data['status'])) # check required fields self.assertIn('PATH', api_data['json'], 'PATH field error') self.assertIn('amqp', api_data['json'], 'amqp field error') self.assertIn('apiServerAddress', api_data['json'], 'apiServerAddress field error') self.assertIn('apiServerPort', api_data['json'], 'apiServerPort field error') self.assertIn('broadcastaddr', api_data['json'], 'broadcastaddr field error') self.assertIn('CIDRNet', api_data['json'], 'CIDRNet field error') self.assertIn('subnetmask', api_data['json'], 'subnetmask field error') self.assertIn('mongo', api_data['json'], 'mongo field error')
def get_rackhd_nodetype(nodeid): nodetype = "" # get the node info mondata = fit_common.rackhdapi("/api/1.1/nodes/" + nodeid) if mondata['status'] != 200: if fit_common.VERBOSITY >= 2: print "Incorrect HTTP return code on nodeid, expected 200, received: {}".format(mondata['status']) else: # get the sku id contained in the node sku = mondata['json'].get("sku") if sku: skudata = fit_common.rackhdapi("/api/1.1/skus/" + sku) if skudata['status'] != 200: if fit_common.VERBOSITY >= 2: print "Incorrect HTTP return code on sku, expected 200, received: {}".format(skudata['status']) else: nodetype = skudata['json'].get("name") else: if fit_common.VERBOSITY >= 2: print "Error: nodeid {} did not return a valid sku in get_rackhd_nodetype{}".format(nodeid, sku) return nodetype
def test_api_20_pollers_catalog(self): # Get poller catalog mon_pollers = fit_common.rackhdapi("/api/2.0/pollers")['json'] # iterate through poller IDs for poller_id in mon_pollers: # check for up to 120 seconds before giving up (pollers go every 60 seconds) max_cycles = 60 sleep_delay = 2 for dummy in range(0, max_cycles): api_data = fit_common.rackhdapi("/api/2.0/pollers/" + poller_id['id'] + "/data") if api_data['status'] == 200: break fit_common.time.sleep(sleep_delay) self.assertEqual(api_data['status'], 200, 'Poller timeout on ID ' + poller_id['id']) # check for data in each poller type for item in api_data['json']: if 'sel' in item: self.assertGreater(len(item['sel']), 0, 'sel' + ' poller data empty') if 'sdr' in item: self.assertGreater(len(item['sdr']), 0, 'sdr' + ' poller data empty')
def test_api_20_templates_metadata(self): api_data = fit_common.rackhdapi("/api/2.0/templates/metadata") self.assertEqual( api_data['status'], 200, "Was expecting code 200. Got " + str(api_data['status'])) for item in api_data['json']: # check required fields for subitem in ['hash', 'id', 'name', 'scope']: if fit_common.VERBOSITY >= 2: print "Checking:", item['name'], subitem self.assertGreater(len(item[subitem]), 0, subitem + ' field error')
def _node_reboot(self, nodeid): # Reboot the node to begin rediscover. logs.debug_3('Running rediscover, resetting system node...') logs.debug('launch AMQP thread') reset_worker = AmqpWorker(exchange_name="on.events", topic_routing_key="graph.#." + nodeid, external_callback=self.amqp_callback, timeout=100) reset_worker.setDaemon(True) reset_worker.start() # Reboot the node, wait reboot workflow start message. response = fit_common.rackhdapi('/redfish/v1/Systems/' + nodeid + '/Actions/ComputerSystem.Reset', action='post', payload={"reset_type": "ForceRestart"}) self.assertTrue( response['status'] < 209, 'Incorrect HTTP return code, expected<209, got:' + str(response['status'])) graphid = response['json']["@odata.id"].split( '/redfish/v1/TaskService/Tasks/')[1] # wait for workflow started message. self._wait_amqp_message(10) workflow_amqp = amqp_queue.get() if workflow_amqp[0][0:14] == "started": self._process_message("started", graphid, nodeid, "graph", workflow_amqp) else: self._process_message("progress.updated", graphid, nodeid, "graph", workflow_amqp) # wait for progress update finish message. self._wait_amqp_message(10) workflow_amqp = amqp_queue.get() self._process_message("progress.updated", graphid, nodeid, "graph", workflow_amqp) # wait for progress finish message. retry_count = 0 while retry_count < 10: self._wait_amqp_message(60) workflow_amqp = amqp_queue.get() if workflow_amqp[0][0:14] == "graph.finished": self._process_message("finished", graphid, nodeid, "graph", workflow_amqp) break retry_count = retry_count + 1 self.assertNotEquals(retry_count, 10, "No AMQP workflow finished message received") reset_worker.dispose()
def test_api_11_workflows_tasks_library(self): api_data = fit_common.rackhdapi("/api/1.1/workflows/tasks/library") self.assertEqual( api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) for item in api_data['json']: if fit_common.VERBOSITY >= 2: print "Checking:", item["friendlyName"] self.assertGreater(len(item['injectableName']), 0, 'injectableName field error') self.assertGreater(len(item['friendlyName']), 0, 'friendlyName field error')
def test_api_20_obms(self): api_data = fit_common.rackhdapi("/api/2.0/obms") self.assertEqual( api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) for item in api_data['json']: # check fields for block in item: if fit_common.VERBOSITY >= 2: print "Checking:", block self.assertGreater(len(str(item[block])), 0, 'Field error: ' + block)
def test_redfish_v1_systems_id_logservices_sel(self): # iterate through node IDs for nodeid in NODECATALOG: api_data = fit_common.rackhdapi("/redfish/v1/Systems/" + nodeid + "/LogServices/sel") if fit_common.VERBOSITY >= 2: print ("nodeid: {0}".format(nodeid)) self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) for item in ['MaxNumberOfRecords', 'OverWritePolicy', 'DateTimeLocalOffset', 'Actions']: if fit_common.VERBOSITY >= 2: print ("Checking: {0}".format(item)) print ("\t {0}".format(api_data['json'][item])) self.assertIn(item, api_data['json'], item + ' field not present') self.assertGreater(len(str(api_data['json'][item])), 0, item + ' field empty')
def check_for_active_pollers(self, max_time): ''' Determine if all poller are active. :param Time to wait (in 10 second intervals) :return: True - Poller active False - Pollers not active ''' for _ in range(0, max_time): api_data = fit_common.rackhdapi('/api/2.0/pollers') if len(api_data['json']) > 0: return True time.sleep(30) return False
def test06_startup(self): print "**** Start services." self.assertEqual( fit_common.remote_shell("/etc/init.d/isc-dhcp-server restart") ['exitcode'], 0, "dhcp startup failure.") self.assertEqual( fit_common.remote_shell( "cd ~/;pm2 start rackhd-pm2-config.yml > /dev/null 2>&1") ['exitcode'], 0, "RackHD startup failure.") print "**** Check installation." fit_common.time.sleep(10) for dummy in range(0, 10): try: fit_common.rackhdapi("/swagger-ui") fit_common.rackhdapi("/api/2.0/config") except: fit_common.time.sleep(10) else: break self.assertEqual( fit_common.rackhdapi("/api/2.0/config")['status'], 200, "Unable to contact RackHD.")
def test_api_11_workflows_put_ipmi(self): data_payload = \ { "friendlyName": "TestIPMI", "injectableName": 'Graph.Obm.Ipmi.CreateSettings.Test', "options": { "obm-ipmi-task":{ "user": "******", "password": "******" } }, "tasks": [ { "label": "obm-ipmi-task", "taskName": "Task.Obm.Ipmi.CreateSettings" } ] } api_data = fit_common.rackhdapi("/api/1.1/workflows", action="put", payload=data_payload) self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) api_data = fit_common.rackhdapi("/api/1.1/workflows/library/" + 'Graph.Obm.Ipmi.CreateSettings.Test') self.assertEqual(api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status']))
def test11_check_node_inventory(self): # this test will verify node inventory by BMC MAC if specified in STACK_CONFIG errorlist = [] #check OBM MAC addresses if "nodes" in fit_common.STACK_CONFIG[fit_common.ARGS_LIST['stack']]: nodecheck = fit_common.rackhdapi('/api/2.0/obms')['text'] for entry in fit_common.STACK_CONFIG[ fit_common.ARGS_LIST['stack']]['nodes']: if entry['bmcmac'] not in str(nodecheck): print '**** Missing node:' + entry[ 'sku'] + " BMC:" + entry['bmcmac'] errorlist.append(entry['bmcmac']) self.assertEqual(errorlist, [], "Missing nodes in catalog.")
def test_api_11_workflows(self): api_data = fit_common.rackhdapi("/api/1.1/workflows") self.assertEqual( api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) for item in api_data['json']: # check required fields for subitem in ['id', 'name', 'updatedAt', 'createdAt']: if fit_common.VERBOSITY >= 2: print "Checking:", item['name'], subitem self.assertGreater(len(item[subitem]), 0, subitem + ' field error')
def test_api_11_nodes_ID_tags(self): # iterate through nodes for nodeid in MON_NODES: #add tag api_data = fit_common.rackhdapi( "/api/1.1/nodes/" + nodeid + "/tags", action="patch", payload={"tags": ["test_tag_" + nodeid]}) self.assertEqual( api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) #check tag api_data = fit_common.rackhdapi("/api/1.1/nodes/" + nodeid + "/tags") self.assertEqual( api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) self.assertIn( "test_tag_" + nodeid, fit_common.json.dumps(api_data['json']), "Tag not set:" + fit_common.json.dumps(api_data['json']))
def test_api_20_catalogs(self): api_data = fit_common.rackhdapi('/api/2.0/catalogs') self.assertEqual( api_data['status'], 200, 'Incorrect HTTP return code, expected 200, got:' + str(api_data['status'])) self.assertNotEqual(len(api_data['json']), 0, "Error, no catalog") for item in api_data['json']: # check required fields for subitem in ['node', 'id', 'source', 'data']: if fit_common.VERBOSITY >= 2: print "Checking:", item['id'], subitem self.assertIn(subitem, item, subitem + ' field error')
def test_rediscover_reboot_kickoff(self): nodeid = self.__get_run_context('start_nodeid') # first setup the web-hook to monitor (see test_rediscover_rackd_discover_hook) for # rackhd hook messages. self.__set_web_hook() # now give the node a kick response = fit_common.rackhdapi( '/redfish/v1/Systems/' + nodeid + '/Actions/ComputerSystem.Reset', action='post', payload={"reset_type": "ForceRestart"}) self.assertTrue( response['status'] < 209, 'Incorrect HTTP return code, expected<209, got:' + str(response['status'])) graphid = response['json']["@odata.id"].split('/redfish/v1/TaskService/Tasks/')[1] self.__set_run_context('reboot_graphid', graphid)