def umount_virtual_media_from_cd(REDFISH_OBJ, members_list, image): """ This function uses the post method to umount virtual media, support AMD server. """ # Get the mount virtual media list for members in members_list: members_url = members["@odata.id"] response_members = REDFISH_OBJ.get(members_url, None) if response_members.status == 200: image_name = response_members.dict["ImageName"] eject_media_url = response_members.dict["Actions"]["#VirtualMedia.EjectMedia"]["target"] else: error_message = utils.get_extended_error(response_members) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( members_url, response_members.status, error_message)} return result if image_name == image: body = {} response = REDFISH_OBJ.post(eject_media_url, body=body) if response.status == 204: result = {'ret': True, 'msg': "'%s' Umount successfully" % image} return result else: error_message = utils.get_extended_error(response) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( eject_media_url, response.status, error_message)} return result else: continue result = {"ret": False, "msg": "Please check the image name is correct and has been mounted."} return result
def umount_virtual_media(REDFISH_OBJ, members_list, image): """ This function uses the patch method to umount virtual media, support 19A version of XCC. """ # Get the mount virtual media list for members in members_list: members_url = members["@odata.id"] if not members_url.split('/')[-1].startswith("Remote"): response_members = REDFISH_OBJ.get(members_url, None) if response_members.status == 200: image_name = response_members.dict["ImageName"] else: error_message = utils.get_extended_error(response_members) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( members_url, response_members.status, error_message)} return result if image_name == image: body = {"Image": None} response = REDFISH_OBJ.patch(members_url, body=body) if response.status == 200: result = {'ret': True, 'msg': "'%s' Umount successfully" % image} return result else: error_message = utils.get_extended_error(response) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( members_url, response.status, error_message)} return result else: continue result = {"ret": False, "msg": "Please check the image name is correct and has been mounted."} return result
def mount_virtual_media_from_network(REDFISH_OBJ, remotemap_url, image, fsip, fsport, fsdir, fsprotocol, fsusername, fspassword, readonly, domain, options): """ This function use the Lenovo OEM extensions for virtual media mount, support mounting up to 4 images concurrently to the server. This function can work on 18D version of XCC and license is "Lenovo XClarity Controller Enterprise". """ response_remotemap_url = REDFISH_OBJ.get(remotemap_url, None) if response_remotemap_url.status == 200: # Get MountImages url from remote map resource instance images_member_url = response_remotemap_url.dict['MountImages']['@odata.id'] headers = {"Content-Type": "application/json"} # Build request body for add images member body = {} protocol = fsprotocol.lower() if protocol == "nfs": body["FilePath"] = fsip + fsport + ":" + fsdir + "/" + image elif protocol == "samba": body["FilePath"] = "//" + fsip + fsport + fsdir + "/" + image elif protocol in ['sftp', 'ftp', 'http']: body["FilePath"] = protocol + "://" + fsip + fsport + fsdir + "/" + image else: result = {'ret': False, 'msg': 'Mount media iso network only support protocol Samba, NFS, HTTP, SFTP/FTP'} return result body["Type"] = fsprotocol body["Username"] = fsusername body["Password"] = fspassword body["Domain"] = domain body["Readonly"] = bool(readonly) body["Options"] = options # Add image member response_images_member = REDFISH_OBJ.post(images_member_url, headers=headers, body=body) if response_images_member.status in [200, 201, 204]: print("Add image member successful.") else: error_message = utils.get_extended_error(response_images_member) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( images_member_url, response_images_member.status, error_message)} return result # Get mount image url form remote map resource instance mount_image_url = response_remotemap_url.dict['Actions']['#LenovoRemoteMapService.Mount']['target'] response_mount_image = REDFISH_OBJ.post(mount_image_url, None) if response_mount_image.status in [200, 204]: result = {'ret': True, 'msg': "'%s' mount successfully" % image} return result else: error_message = utils.get_extended_error(response_mount_image) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( mount_image_url, response_mount_image.status, error_message)} return result else: error_message = utils.get_extended_error(response_remotemap_url) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( remotemap_url, response_remotemap_url.status, error_message)} return result
def task_monitor(REDFISH_OBJ, task_uri): """Monitor task status""" END_TASK_STATE = [ "Cancelled", "Completed", "Exception", "Killed", "Interrupted", "Suspended", "Done", "Failed when Flashing Image." ] print("Start to update the firmware, please wait a few minutes...") while True: response_task_uri = REDFISH_OBJ.get(task_uri, None) if response_task_uri.status == 200: if "TaskState" in response_task_uri.dict: task_state = response_task_uri.dict["TaskState"] elif "Oem" in response_task_uri.dict: if "UpdateStatus" in response_task_uri.dict['Oem']: task_state = response_task_uri.dict["Oem"]["UpdateStatus"] else: task_state = "Exception" else: task_state = "Exception" # Monitor task status until the task terminates if task_state in END_TASK_STATE: result = {'ret': True, 'msg': task_state} return result else: update_firmware.flush() else: message = utils.get_extended_error(response_task_uri) result = { 'ret': False, 'msg': "Url '%s' response Error code %s, \nError message :%s" % (task_uri, response_task_uri.status, message) } return result
def mount_virtual_media(REDFISH_OBJ, members_list, protocol, fsip, fsport, fsdir, image, writeprotocol, inserted, fsusername=None, fspassword=None): """ This function uses the patch method to mount VM, only HTTP and NFS(no credential required) protocols are supported. This function can work on 19A version of XCC and license is "Lenovo XClarity Controller Enterprise". """ # Get the members url from the members list for members in members_list: members_url = members["@odata.id"] if members_url.split('/')[-1].startswith("EXT"): # Get the mount image name from the members response resource response_members = REDFISH_OBJ.get(members_url, None) if response_members.status == 200: image_name = response_members.dict["ImageName"] else: error_message = utils.get_extended_error(response_members) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( members_url, response_members.status, error_message)} return result # Via patch request mount virtual media if image_name is None: body = {} if protocol == "nfs": image_uri = fsip + fsport + ":" + fsdir + "/" + image elif protocol == "cifs": image_uri = "//" + fsip + fsport + fsdir + "/" + image body = {"Image": image_uri, "TransferProtocolType": protocol.upper(), "UserName": fsusername, "Password": fspassword, "WriteProtected": bool(writeprotocol), "Inserted": bool(inserted)} else: image_uri = protocol + "://" + fsip + fsport + fsdir + "/" + image if protocol != "cifs": body = {"Image": image_uri, "WriteProtected": bool(writeprotocol), "Inserted": bool(inserted)} response = REDFISH_OBJ.patch(members_url, body=body) if response.status in [200, 204]: result = {'ret': True, 'msg': "'%s' mount successfully" % image} return result else: error_message = utils.get_extended_error(response) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( members_url, response.status, error_message)} return result else: continue result = {'ret': False, 'msg': "Up to 4 files can be concurrently mounted to the server by the BMC."} return result
def mount_virtual_media_from_rdoc(REDFISH_OBJ, remotecontrol_url, remotemap_url, source_url, fsusername, fspassword, fsprotocol, readonly, domain, options): """ This function use the Lenovo OEM extensions for VM mount, support mounting 2 RDOC images and maximum amount sizes of RDOC images are 50MB. This function can work on 18D version of XCC and license is "Lenovo XClarity Controller Advanced". """ # Upload the mount image via file server response_remotecontrol_url = REDFISH_OBJ.get(remotecontrol_url, None) if response_remotecontrol_url.status == 200: # Get upload media iso url from remoto control resource instance upload_url = response_remotecontrol_url.dict['Actions']['#LenovoRemoteControlService.UploadFromURL']['target'] body = {"sourceURL": source_url, "Username": fsusername, "Password": fspassword, "Type": fsprotocol, "Readonly": bool(readonly), "Domain": domain, "Options": options} response_upload_url = REDFISH_OBJ.post(upload_url, body=body) if response_upload_url.status in [200, 204]: print("Upload media iso successful, next will mount media iso...") else: error_message = utils.get_extended_error(response_upload_url) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( upload_url, response_upload_url.status, error_message)} return result else: error_message = utils.get_extended_error(response_remotecontrol_url) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( remotecontrol_url, response_remotecontrol_url.status, error_message)} return result # Mount the virtual media response_remotemap_url = REDFISH_OBJ.get(remotemap_url, None) if response_remotemap_url.status == 200: # Get mount image url form remote map resource instance mount_image_url = response_remotemap_url.dict['Actions']['#LenovoRemoteMapService.Mount']['target'] response_mount_image = REDFISH_OBJ.post(mount_image_url, body={}) if response_mount_image.status in [200, 204]: image = source_url.split('/')[-1] result = {'ret': True, 'msg': "'%s' mount successfully" % image} return result else: error_message = utils.get_extended_error(response_mount_image) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( mount_image_url, response_mount_image.status, error_message)} return result else: error_message = utils.get_extended_error(response_remotemap_url) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( remotemap_url, response_remotemap_url.status, error_message)} return result
def task_monitor(REDFISH_OBJ, task_uri): """Monitor task status""" RUNNING_TASK_STATE = [ "New", "Pending", "Service", "Starting", "Stopping", "Running", "Cancelling", "Verifying" ] END_TASK_STATE = [ "Cancelled", "Completed", "Exception", "Killed", "Interrupted", "Suspended" ] current_state = "" while True: response_task_uri = REDFISH_OBJ.get(task_uri, None) if response_task_uri.status == 200: task_state = response_task_uri.dict["TaskState"] if task_state in RUNNING_TASK_STATE: if task_state != current_state: current_state = task_state print('Task state is %s, wait a minute' % current_state) continue else: flush() elif task_state.startswith("Downloading"): sys.stdout.write(' ' * 100 + '\r') sys.stdout.flush() sys.stdout.write(task_state + '\r') sys.stdout.flush() continue elif task_state.startswith("Update"): sys.stdout.write(' ' * 100 + '\r') sys.stdout.flush() sys.stdout.write(task_state + '\r') sys.stdout.flush() continue elif task_state in END_TASK_STATE: print("End of the task") result = {'ret': True, 'msg': task_state} return result else: result = { "ret": False, "msg": "Task Not conforming to Schema Specification" } return result else: message = utils.get_extended_error(response_task_uri) result = { 'ret': False, 'msg': "Url '%s' response Error code %s, \nError message :%s" % (task_uri, response_task_uri.status, message) } return result
def mount_virtual_media_from_cd(REDFISH_OBJ, members_list, protocol, fsip, fsport, fsdir, image, fsusername=None, fspassword=None): """ This function user the post method to mount VM, only NFS protocols are supported. This function can work on AMD server. """ # Get the members url from the members list if not image.endswith(".iso") and not image.endswith(".nrg"): result = {'ret': False, 'msg': "Supported CD/DVD media file type: (*.iso), (*.nrg)."} return result for members in members_list: members_url = members["@odata.id"] # Get the mount image name from the members response resource response_members = REDFISH_OBJ.get(members_url, None) if response_members.status == 200: image_name = response_members.dict["ImageName"] insert_media_url = response_members.dict["Actions"]["#VirtualMedia.InsertMedia"]["target"] else: error_message = utils.get_extended_error(response_members) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( members_url, response_members.status, error_message)} return result if not image_name: image_uri = protocol + "://" + fsip + fsport + fsdir + "/" + image if protocol == 'nfs': body = {"Image": image_uri, "TransferProtocolType": protocol.upper()} else: body = {"Image": image_uri, "TransferProtocolType": protocol.upper(), "UserName": fsusername, "Password": fspassword} response = REDFISH_OBJ.post(insert_media_url, body=body) if response.status in [200, 204]: result = {'ret': True, 'msg': "'%s' mount successfully" % image} return result else: error_message = utils.get_extended_error(response) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( insert_media_url, response.status, error_message)} return result else: continue result = {'ret': False, 'msg': "Up to 4 files can be concurrently mounted to the server by the BMC."} return result
def task_monitor(REDFISH_OBJ, task_uri): """Monitor task status""" END_TASK_STATE = [ "Cancelled", "Completed", "Exception", "Killed", "Interrupted", "Suspended", "Done", "Failed when Flashing Image." ] time_start = time.time() print("Start to refresh the firmware, please wait about 3~10 minutes...") while True: response_task_uri = REDFISH_OBJ.get(task_uri, None) if response_task_uri.status in [200, 202]: if "TaskState" in response_task_uri.dict: task_state = response_task_uri.dict["TaskState"] elif "Oem" in response_task_uri.dict: if "UpdateStatus" in response_task_uri.dict['Oem']: task_state = response_task_uri.dict["Oem"]["UpdateStatus"] else: task_state = "Exception" else: task_state = "Exception" # Monitor task status until the task terminates if task_state in END_TASK_STATE: result = { 'ret': True, 'task_state': task_state, 'id': response_task_uri.dict['Id'] } return result else: time_now = time.time() # wait for max 10 minutes to avoid endless loop. if time_now - time_start > 600: result = { 'ret': False, 'task_state': task_state, 'msg': "It took too long time to update the firmware, over 10 minutes. Task id is %s ." % response_task_uri.dict['Id'] } return result time.sleep(10) else: message = utils.get_extended_error(response_task_uri) result = { 'ret': False, 'msg': "Url '%s' response Error code %s, \nError message :%s" % (task_uri, response_task_uri.status, message) } return result
def raw_command_patch(ip, login_account, login_password, resource_uri, body): """Patch specified resource :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :params resource_uri: redfish resource uri :type resource_uri: string :params body: json string body for redfish patch request :type body: string :returns: returns specified resource information when succeeded or error message when failed """ result = {} login_host = "https://" + ip try: # Connect using the BMC address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, timeout=utils.g_timeout, password=login_password, default_prefix='/redfish/v1', cafile=utils.g_CAFILE, max_retry=3) # Login into the server and create a session REDFISH_OBJ.login(auth=utils.g_AUTH) except Exception as e: traceback.print_exc() result = {'ret': False, 'msg': "Error_message: %s. Please check if username, password and IP are correct" % repr(e)} return result request_url = resource_uri headers = {"If-Match": "*"} response_url = REDFISH_OBJ.patch(request_url, body=json.loads(body), headers=headers) if response_url.status not in [200, 204]: error_message = utils.get_extended_error(response_url) result = {'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % ( request_url, response_url.status, error_message)} REDFISH_OBJ.logout() return result message_extendedinfo = "" if response_url.status == 200 and "@Message.ExtendedInfo" in response_url.dict: message_extendedinfo = "@Message.ExtendedInfo: " + str(response_url.dict["@Message.ExtendedInfo"]) result['ret'] = True result['msg'] = "Update resource uri %s successfully. %s" %(resource_uri, message_extendedinfo) # Logout of the current session try: REDFISH_OBJ.logout() except: pass return result
def umount_all_virtual_from_network(REDFISH_OBJ, remotemap_url): """ This function use the Lenovo OEM extensions to umount virtual media from Network, support 18D version of XCC. """ response_remotemap_url = REDFISH_OBJ.get(remotemap_url, None) if response_remotemap_url.status == 200: # Get umount image url form remote map resource instance umount_image_url = response_remotemap_url.dict['Actions']['#LenovoRemoteMapService.UMount']['target'] response_umount_image = REDFISH_OBJ.post(umount_image_url, None) if response_umount_image.status in [200, 204]: result = {'ret': True, 'msg': "All Media File from Network umount successfully"} return result else: error_message = utils.get_extended_error(response_umount_image) result = {'ret': False, 'msg': "Umount media iso failed, '%s' response Error code %s \nerror_message: %s" % ( remotemap_url, response_umount_image.status, error_message)} return result else: error_message = utils.get_extended_error(response_remotemap_url) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( remotemap_url, response_remotemap_url.status, error_message)} return result
def raw_command_get(ip, login_account, login_password, resource_uri): """Get specified resource information :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :params resource_uri: redfish resource uri :type resource_uri: string :returns: returns specified resource information when succeeded or error message when failed """ result = {} login_host = "https://" + ip try: # Connect using the BMC address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, timeout=utils.g_timeout, password=login_password, default_prefix='/redfish/v1', cafile=utils.g_CAFILE, max_retry=3) # Login into the server and create a session REDFISH_OBJ.login(auth=utils.g_AUTH) except Exception as e: traceback.print_exc() result = {'ret': False, 'msg': "Error_message: %s. Please check if username, password and IP are correct" % repr(e)} return result request_url = resource_uri response_url = REDFISH_OBJ.get(request_url, None) if response_url.status != 200: error_message = utils.get_extended_error(response_url) result = {'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % ( request_url, response_url.status, error_message)} REDFISH_OBJ.logout() return result resource_details = response_url.dict result['ret'] = True result['data'] = resource_details # Logout of the current session try: REDFISH_OBJ.logout() except: pass return result
def lenovo_get_ssh_pubkey(ip, login_account, login_password, user_name): """Get SSH pubkey :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :params user_name: user name :type user_name: string :returns: returns ssh pubkey info when succeeded or error message when failed """ result = {} login_host = "https://" + ip try: # Connect using the BMC address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, password=login_password, default_prefix='/redfish/v1') # Login into the server and create a session REDFISH_OBJ.login(auth="session") except: result = { 'ret': False, 'msg': "Please check the username, password, IP is correct" } return result #If not specified, login username will be used if user_name is None or user_name == '': user_name = login_account try: # GET the Accounts resource response_base_url = REDFISH_OBJ.get("/redfish/v1", None) if response_base_url.status == 200: account_service_url = response_base_url.dict["AccountService"][ "@odata.id"] else: error_message = utils.get_extended_error(response_base_url) result = { 'ret': False, 'msg': "Url '/redfish/v1' response Error code %s\nerror_message: %s" % (response_base_url.status, error_message) } return result response_account_service_url = REDFISH_OBJ.get(account_service_url, None) if response_account_service_url.status == 200: accounts_url = response_account_service_url.dict["Accounts"][ "@odata.id"] else: error_message = utils.get_extended_error( response_account_service_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (account_service_url, response_account_service_url.status, error_message) } return result # Get all BMC user account accounts_url_response = REDFISH_OBJ.get(accounts_url, None) if accounts_url_response.status == 200: # Loop through Accounts and print info account_url_list = accounts_url_response.dict["Members"] for account_dict in account_url_list: account_url = account_dict["@odata.id"] account_url_response = REDFISH_OBJ.get(account_url) if account_url_response.status == 200: if user_name == account_url_response.dict["UserName"]: pubkey_dict = {} pubkey_dict["Id"] = account_url_response.dict["Id"] pubkey_dict["UserName"] = user_name try: pubkey_dict[ "SSHPublicKey"] = account_url_response.dict[ "Oem"]["Lenovo"]["SSHPublicKey"] except: result = { "ret": False, "msg": "Not support resource Oem.Lenovo.SSHPublicKey in Account" } return result result = {"ret": True, "entries": pubkey_dict} return result else: error_message = utils.get_extended_error( account_url_response) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (account_url, account_url_response.status, error_message) } return result result = { "ret": False, "msg": "User name is not existed,Please check your input" } return result else: error_message = utils.get_extended_error(accounts_url_response) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (accounts_url, accounts_url_response.status, error_message) } return result except Exception as e: result = {'ret': False, 'msg': "Error message %s" % e} finally: # Logout of the current session try: REDFISH_OBJ.logout() except: pass return result
def get_chassis_indicator_led(ip, login_account, login_password): """Get chassis indicator led :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :returns: returns get chassis indicator led status when succeeded or error message when failed """ result = {} login_host = "https://" + ip try: # Connect using the BMC address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, password=login_password, default_prefix='/redfish/v1') # Login into the server and create a session REDFISH_OBJ.login(auth="session") except: result = { 'ret': False, 'msg': "Please check the username, password, IP is correct\n" } return result try: # Get ComputerBase resource response_base_url = REDFISH_OBJ.get('/redfish/v1', None) # Get response_base_url if response_base_url.status == 200: chassis_url = response_base_url.dict['Chassis']['@odata.id'] else: error_message = utils.get_extended_error(response_base_url) result = { 'ret': False, 'msg': "Url '/redfish/v1' response Error code %s \nerror_message: %s" % (response_base_url.status, error_message) } return result # Get response chassis url resource response_chassis_url = REDFISH_OBJ.get(chassis_url, None) if response_chassis_url.status == 200: # Get the LED status for i in range(response_chassis_url.dict['*****@*****.**']): led_status = {} led_url = response_chassis_url.dict['Members'][i]['@odata.id'] response_led_url = REDFISH_OBJ.get(led_url, None) if response_led_url.status == 200: if response_chassis_url.dict[ '*****@*****.**'] > 1 and "ComputerSystems" not in response_led_url.dict[ "Links"]: continue led_status["indicatorLED"] = response_led_url.dict[ 'IndicatorLED'] result = {'ret': True, 'msg': led_status} return result else: error_message = utils.get_extended_error(response_led_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % (led_url, response_led_url.status, error_message) } return result else: error_message = utils.get_extended_error(response_chassis_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % (chassis_url, response_chassis_url.status, error_message) } return result except Exception as e: result = {'ret': False, 'msg': "error_message: %s" % e} finally: # Logout of the current session REDFISH_OBJ.logout() return result
def get_memory_inventory(ip, login_account, login_password, system_id, member_id): """Get memory inventory :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :params system_id: ComputerSystem instance id(None: first instance, All: all instances) :type system_id: None or string :params member_id: Memory member id :type member_id: None or int :returns: returns memory inventory when succeeded or error message when failed """ result = {} login_host = "https://" + ip try: # Connect using the BMC address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, password=login_password, default_prefix='/redfish/v1') # Login into the server and create a session REDFISH_OBJ.login(auth="session") except: result = { 'ret': False, 'msg': "Please check the username, password, IP is correct" } return result system_details = [] # GET the ComputerSystem resource try: system = utils.get_system_url("/redfish/v1", system_id, REDFISH_OBJ) if not system: result = { 'ret': False, 'msg': "This system id is not exist or system member is None" } return result list_memory_info = [] for i in range(len(system)): system_url = system[i] response_system_url = REDFISH_OBJ.get(system_url, None) if response_system_url.status == 200: memroys_url = response_system_url.dict["Memory"]["@odata.id"] response_memory_url = REDFISH_OBJ.get(memroys_url, None) if response_memory_url.status == 200: list_memory_url = response_memory_url.dict["Members"] # check member_id validity if member_id != None: if member_id <= 0 or member_id > len(list_memory_url): result = { 'ret': False, 'msg': "Specified member id is not valid. The id should be within 1~%s" % (len(list_memory_url)) } REDFISH_OBJ.logout() return result # get each memory info index = 1 for memory_dict in list_memory_url: if member_id != None and index != member_id: index = index + 1 continue index = index + 1 sub_memory_url = memory_dict["@odata.id"] response_sub_memory_url = REDFISH_OBJ.get( sub_memory_url, None) if response_sub_memory_url.status == 200: memory_info = {} if response_sub_memory_url.dict["Status"][ "State"] == "Absent": memory_info[ "Status"] = response_sub_memory_url.dict[ "Status"] memory_info[ "MemoryLocation"] = response_sub_memory_url.dict[ "MemoryLocation"] memory_info[ "Id"] = response_sub_memory_url.dict["Id"] list_memory_info.append(memory_info) continue for key in response_sub_memory_url.dict: if key == "Links" or key.startswith( "@") or key == "Oem": continue else: memory_info[ key] = response_sub_memory_url.dict[ key] list_memory_info.append(memory_info) else: error_message = utils.get_extended_error( response_sub_memory_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (sub_memory_url, response_sub_memory_url.status, error_message) } return result else: error_message = utils.get_extended_error( response_memory_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\n error_message: %s" % (memroys_url, response_memory_url.status, error_message) } return result else: error_message = utils.get_extended_error(response_system_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\n error_message: %s" % (system_url, response_system_url.status, error_message) } return result result['ret'] = True result['entries'] = list_memory_info return result except Exception as e: result = {'ret': False, 'msg': "exception msg %s" % e} return result finally: REDFISH_OBJ.logout()
def get_storage_inventory(ip, login_account, login_password, system_id): """Get storage inventory :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :params system_id: ComputerSystem instance id(None: first instance, All: all instances) :type system_id: None or string :returns: returns storage inventory when succeeded or error message when failed """ result = {} login_host = "https://" + ip try: # Connect using the BMC address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, timeout=utils.g_timeout, password=login_password, default_prefix='/redfish/v1', cafile=utils.g_CAFILE) # Login into the server and create a session REDFISH_OBJ.login(auth=utils.g_AUTH) except: traceback.print_exc() result = { 'ret': False, 'msg': "Please check the username, password, IP is correct" } return result storage_details = [] # GET the ComputerSystem resource system = utils.get_system_url("/redfish/v1", system_id, REDFISH_OBJ) if not system: result = { 'ret': False, 'msg': "This system id is not exist or system member is None" } REDFISH_OBJ.logout() return result for i in range(len(system)): system_url = system[i] response_system_url = REDFISH_OBJ.get(system_url, None) if response_system_url.status == 200: # GET the Storage resources from the ComputerSystem resource if "Storage" in response_system_url.dict: storage_url = response_system_url.dict["Storage"]["@odata.id"] else: storage_url = response_system_url.dict["SimpleStorage"][ "@odata.id"] response_storage_url = REDFISH_OBJ.get(storage_url, None) if response_storage_url.status == 200: storage_count = len(response_storage_url.dict["Members"]) storage = 0 for nic in range(0, storage_count): storage_x_url = response_storage_url.dict["Members"][nic][ "@odata.id"] response_storage_x_url = REDFISH_OBJ.get( storage_x_url, None) if response_storage_x_url.status == 200: storage = {} Storage_id = response_storage_x_url.dict["Id"] Name = response_storage_x_url.dict["Name"] storage['Id'] = Storage_id storage['Name'] = Name # Get the disk inventory from each of the disk resources drive_list = [] if "Drives" in response_storage_x_url.dict: for disk in response_storage_x_url.dict["Drives"]: disk_inventory = {} disk_url = disk["@odata.id"] response_disk_url = REDFISH_OBJ.get( disk_url, None) if response_disk_url.status == 200: for key in response_disk_url.dict: if key not in [ "Description", "@odata.context", "@odata.id", "@odata.type", "@odata.etag", "Links", "Actions", "RelatedItem" ]: disk_inventory[ key] = response_disk_url.dict[ key] drive_list.append(disk_inventory) else: error_message = utils.get_extended_error( response_disk_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (disk_url, response_disk_url.status, error_message) } return result storage['Drives'] = drive_list if "Volumes" in response_storage_x_url.dict: volumes_url = response_storage_x_url.dict[ "Volumes"]["@odata.id"] response_volumes_url = REDFISH_OBJ.get( volumes_url, None) if response_volumes_url.status == 200: volumes_list = [] for volume in response_volumes_url.dict[ "Members"]: volume_inventory = {} volume_url = volume["@odata.id"] response_volume_url = REDFISH_OBJ.get( volume_url, None) if response_volume_url.status == 200: for key in response_volume_url.dict: if key not in [ "Description", "@odata.context", "@odata.id", "@odata.type", "@odata.etag", "Links", "Actions", "RelatedItem" ]: volume_inventory[ key] = response_volume_url.dict[ key] volumes_list.append(volume_inventory) else: error_message = utils.get_extended_error( response_volume_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (volume_url, response_volume_url.status, error_message) } return result else: error_message = utils.get_extended_error( response_volumes_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (volumes_url, response_volumes_url.status, error_message) } return result storage['Volumes'] = volumes_list controller_count = response_storage_x_url.dict[ "*****@*****.**"] # GET the StorageControllers instances resources from each of the Storage resources storage_list = [] for controller in range(0, controller_count): storage_controller = {} for key in response_storage_x_url.dict[ "StorageControllers"][controller]: if key not in [ "Description", "@odata.context", "@odata.id", "@odata.type", "@odata.etag", "Links", "Actions", "RelatedItem" ]: storage_controller[ key] = response_storage_x_url.dict[ "StorageControllers"][controller][ key] storage_list.append(storage_controller) storage['storage_controller'] = storage_list storage_details.append(storage) else: result = { 'ret': False, 'msg': "response_storage_x_url code %s" % response_storage_x_url.status } REDFISH_OBJ.logout() return result else: result = { 'ret': False, 'msg': "response storage url Error code %s" % response_storage_url.status } REDFISH_OBJ.logout() else: result = { 'ret': False, 'msg': "response_system_url Error code %s" % response_system_url.status } REDFISH_OBJ.logout() return result result['ret'] = True result['entries'] = storage_details # Logout of the current session try: REDFISH_OBJ.logout() except: pass return result
def set_service_port(ip, login_account, login_password, service, enabled, port): """This feature provides abilities to enable or disable a BMC service and to change port numbers :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :params service: Specify service information supported by BMC. Support:["HTTPS","SSDP","SSH","SNMP","IPMI","VirtualMedia"] :type service: string :params enabled: Disable(0) or enable(1) the BMC service :type enabled: int :params port: The value of this property shall contain the port assigned for the protocol :type port: int :returns: returns Get bmc ntp result when succeeded or error message when failed """ result = {} login_host = "https://" + ip # Connect using the BMC address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, password=login_password, default_prefix='/redfish/v1', cafile=utils.g_CAFILE) # Login into the server and create a session try: REDFISH_OBJ.login(auth=utils.g_AUTH) except: result = { 'ret': False, 'msg': "Please check the username, password, IP is correct\n" } return result # Get ServiceBase resource try: response_base_url = REDFISH_OBJ.get('/redfish/v1', None) # Get response_base_url if response_base_url.status == 200: managers_url = response_base_url.dict['Managers']['@odata.id'] else: error_message = utils.get_extended_error(response_base_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % ('/redfish/v1', response_base_url.status, error_message) } return result response_managers_url = REDFISH_OBJ.get(managers_url, None) if response_managers_url.status == 200: for request in response_managers_url.dict['Members']: request_url = request['@odata.id'] response_url = REDFISH_OBJ.get(request_url, None) #Get Network Protocol url from the manager url response if response_url.status == 200: network_protocol_url = response_url.dict[ "NetworkProtocol"]['@odata.id'] else: error_message = utils.get_extended_error(response_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (request_url, response_url.status, error_message) } return result # get etag to set If-Match precondition response_network_protocol_url = REDFISH_OBJ.get( network_protocol_url, None) if response_network_protocol_url.status != 200: error_message = utils.get_extended_error( response_network_protocol_url) result = { 'ret': False, 'msg': "Url '%s' get failed. response Error code %s \nerror_message: %s" % (network_protocol_url, response_network_protocol_url.status, error_message) } return result if "@odata.etag" in response_network_protocol_url.dict: etag = response_network_protocol_url.dict['@odata.etag'] else: etag = "" headers = {"If-Match": etag} # Build request body for modify network protocol if service in ["IPMI", "SSDP"]: body = {service: {"ProtocolEnabled": bool(int(enabled))}} elif service in ["SSH", "HTTPS", "SNMP", "VirtualMedia"]: body = { service: { "ProtocolEnabled": bool(int(enabled)), "Port": port } } else: result = { 'ret': False, 'msg': "Please check the BMC service name is in the [HTTPS,HTTP,SSDP,SSH,SNMP,IPMI,VirtualMedia]" } return result # Send Patch Request to Modify Network Port response_network_protocol_url = REDFISH_OBJ.patch( network_protocol_url, body=body, headers=headers) if response_network_protocol_url.status in [200, 204]: result = { 'ret': True, 'msg': "Set BMC service %s successfully" % service } return result else: error_message = utils.get_extended_error( response_network_protocol_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (network_protocol_url, response_network_protocol_url.status, error_message) } return result else: error_message = utils.get_extended_error(response_managers_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (managers_url, response_managers_url.status, error_message) } return result except Exception as e: traceback.print_exc() result = {'ret': False, 'msg': 'exception msg %s' % e} return result finally: REDFISH_OBJ.logout()
def set_bios_password(ip, login_account, login_password, system_id, bios_password_name, bios_password, oldbiospass): """Set Bios password :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :params system_id: ComputerSystem instance id(None: first instance, All: all instances) :type system_id: None or string :params bios_password_name: Bios password name by user specified :type bios_password_name: string :params bios_password: Bios password by user specified :type bios_password: string :params oldbiospass: Old Bios password :type oldbiospass: None or string :returns: returns set bios password result when succeeded or error message when failed """ result = {} login_host = "https://" + ip try: # Connect using the BMC address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, password=login_password, default_prefix='/redfish/v1', cafile=utils.g_CAFILE) # Login into the server and create a session REDFISH_OBJ.login(auth=utils.g_AUTH) except: result = { 'ret': False, 'msg': "Please check the username, password, IP is correct" } return result try: # GET the ComputerSystem resource system = utils.get_system_url("/redfish/v1", system_id, REDFISH_OBJ) if not system: result = { 'ret': False, 'msg': "This system id is not exist or system member is None" } return result for i in range(len(system)): system_url = system[i] response_system_url = REDFISH_OBJ.get(system_url, None) if response_system_url.status == 200: # Get the ComputerBios resource if len(system) > 1 and 'Bios' not in response_system_url.dict: continue bios_url = response_system_url.dict['Bios']['@odata.id'] else: error_message = utils.get_extended_error(response_system_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % (system_url, response_system_url.status, error_message) } return result response_bios_url = REDFISH_OBJ.get(bios_url, None) if response_bios_url.status == 200: # Get password name allowable value list attribute_registry = response_bios_url.dict[ 'AttributeRegistry'] registry_url = "/redfish/v1/Registries" bios_registry_url = "" registry_response = REDFISH_OBJ.get(registry_url, None) if registry_response.status == 200: members_list = registry_response.dict["Members"] for registry in members_list: if attribute_registry in registry["@odata.id"]: bios_registry_url = registry["@odata.id"] bios_registry_json_url = "" if bios_registry_url != "": bios_registry_response = REDFISH_OBJ.get( bios_registry_url, None) if bios_registry_response.status == 200: bios_registry_json_url = bios_registry_response.dict[ "Location"][0]["Uri"] bios_attribute_list = [] if bios_registry_json_url != "": bios_registry_json_response = REDFISH_OBJ.get( bios_registry_json_url, None) if bios_registry_json_response.status == 200: bios_attribute_list = bios_registry_json_response.dict[ "RegistryEntries"]["Attributes"] password_allowed_values = [] for bios_attribute in bios_attribute_list: AttributeName = bios_attribute["AttributeName"] AttributeType = bios_attribute["Type"] if AttributeType == "Password": password_allowed_values.append(AttributeName) if len(password_allowed_values) == 0: if "*****@*****.**" in response_bios_url.dict[ "Actions"]["#Bios.ChangePassword"]: password_allowed_values = response_bios_url.dict[ "Actions"]["#Bios.ChangePassword"][ "*****@*****.**"] # Check whether password name is in allowable value list if len( password_allowed_values ) != 0 and bios_password_name not in password_allowed_values: result = { 'ret': False, 'msg': "Specified password name is not included in allowable value list. Please select password name from list: %s" % (str(password_allowed_values)) } return result # get parameter requirement if ActionInfo is provided if "@Redfish.ActionInfo" in response_bios_url.dict["Actions"][ "#Bios.ChangePassword"]: actioninfo_url = response_bios_url.dict["Actions"][ "#Bios.ChangePassword"]["@Redfish.ActionInfo"] response_actioninfo_url = REDFISH_OBJ.get( actioninfo_url, None) if (response_actioninfo_url.status == 200) and ("Parameters" in response_actioninfo_url.dict): for parameter in response_actioninfo_url.dict[ "Parameters"]: if ("OldPassword" == parameter["Name"]) and ( True == parameter["Required"]): if oldbiospass == None: result = { 'ret': False, 'msg': "Required parameter oldbiospasswd need to be specified." } return result # Get the change password url change_password_url = response_bios_url.dict['Actions'][ '#Bios.ChangePassword']['target'] # Set Password info requestbody = {} PasswordName = bios_password_name new_password = bios_password if oldbiospass == None: requestbody = { "PasswordName": PasswordName, "NewPassword": new_password } else: requestbody = { "PasswordName": PasswordName, "NewPassword": new_password, "OldPassword": oldbiospass } # Change password response_change_password = REDFISH_OBJ.post( change_password_url, body=requestbody) if response_change_password.status in [200, 204]: result = { 'ret': True, 'msg': 'Setting BIOS password successfully' } # Note: For SR635 and SR655 servers, if new password not meet BIOS password policy requirement, # redfish API may fail to identify errors and return success. In this case, # new BIOS password is not set in server, you should use original BIOS password. else: error_message = utils.get_extended_error( response_change_password) result = { 'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % (change_password_url, response_change_password.status, error_message) } return result else: error_message = utils.get_extended_error(response_bios_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % (bios_url, response_bios_url.status, error_message) } return result except Exception as e: result = {'ret': False, 'msg': "error_message: %s" % (e)} finally: # Logout of the current session try: REDFISH_OBJ.logout() except: pass return result
def disable_bmc_user(ip, login_account, login_password, username): """Disable user :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :params username: Specify the BMC user name to be disabled. :type username: None or string :returns: returns disable user result when succeeded or error message when failed """ result = {} login_host = "https://" + ip try: # Connect using the BMC address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, password=login_password, default_prefix='/redfish/v1', cafile=utils.g_CAFILE) # Login into the server and create a session REDFISH_OBJ.login(auth=utils.g_AUTH) except: result = { 'ret': False, 'msg': "Please check the username, password, IP is correct\n" } return result try: # Get response_base_url resource response_base_url = REDFISH_OBJ.get('/redfish/v1', None) # Get account service url if response_base_url.status == 200: account_service_url = response_base_url.dict['AccountService'][ '@odata.id'] else: error_message = utils.get_extended_error(response_base_url) result = { 'ret': False, 'msg': "Url '/redfish/v1' response Error code %s \nerror_message: %s" % (response_base_url.status, error_message) } return result # Get AccountService resource response_account_service_url = REDFISH_OBJ.get(account_service_url, None) if response_account_service_url.status == 200: accounts_url = response_account_service_url.dict['Accounts'][ '@odata.id'] else: error_message = utils.get_extended_error( response_account_service_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % (account_service_url, response_account_service_url.status, error_message) } return result # Get url accounts resource response_accounts_url = REDFISH_OBJ.get(accounts_url, None) if response_accounts_url.status == 200: account_count = response_accounts_url.dict["*****@*****.**"] # Loop the BMC user list and get all the bmc username for x in range(0, account_count): account_x_url = response_accounts_url.dict["Members"][x][ "@odata.id"] response_account_x_url = REDFISH_OBJ.get(account_x_url, None) if response_account_x_url.status == 200: bmc_username = response_account_x_url.dict['UserName'] # Disabled the BMC user when the specified BMC username is in the BMC user list. if bmc_username == username: Enabled = response_account_x_url.dict['Enabled'] if Enabled is False: result = { 'ret': True, 'msg': "BMC user %s is already disabled" % username } return result # Set the body info if "@odata.etag" in response_account_x_url.dict: etag = response_account_x_url.dict['@odata.etag'] else: etag = "" headers = {"If-Match": etag} parameter = {"Enabled": False, "UserName": username} response_enable_user = REDFISH_OBJ.patch( account_x_url, body=parameter, headers=headers) if response_enable_user.status in [200, 204]: result = { 'ret': True, 'msg': "BMC User %s disabled successfully" % username } return result else: error_message = utils.get_extended_error( response_enable_user) result = { 'ret': False, 'msg': "Disabled BMC user failed, url '%s' response Error code %s \nerror_message: %s" % (account_x_url, response_enable_user.status, error_message) } return result else: error_message = utils.get_extended_error( response_account_x_url) result = { 'ret': False, 'msg': "Url '%s' response error code %s \nerror_message: %s" % (account_x_url, response_account_x_url.status, error_message) } return result result = { 'ret': False, 'msg': "Specified BMC username doesn't exist. Please check whether the BMC username is correct." } else: error_message = utils.get_extended_error(response_accounts_url) result = { 'ret': False, 'msg': "Url '%s' response error code %s \nerror_message: %s" % (accounts_url, response_accounts_url.status, error_message) } except Exception as e: result = {'ret': False, 'msg': "error message %s" % e} finally: # Logout of the current session try: REDFISH_OBJ.logout() except: pass return result
def get_bios_attribute(ip, login_account, login_password, system_id, attribute_name): """get bios attribute by user specified :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :params system_id: ComputerSystem instance id(None: first instance, All: all instances) :type system_id: None or string :params attribute_name: Bios attribute name by user specified :type attribute_name: string :returns: returns get bios attribute value when succeeded or error message when failed """ result = {} try: # Connect using the BMC address, account name, and password # Create a REDFISH object login_host = "https://" + ip REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, password=login_password, default_prefix='/redfish/v1') # Login into the server and create a session REDFISH_OBJ.login(auth="session") except: result = { 'ret': False, 'msg': "Please check the username, password, IP is correct" } return result try: # GET the ComputerSystem resource system = utils.get_system_url("/redfish/v1", system_id, REDFISH_OBJ) if not system: result = { 'ret': False, 'msg': "This system id is not exist or system member is None" } return result for i in range(len(system)): system_url = system[i] response_system_url = REDFISH_OBJ.get(system_url, None) if response_system_url.status == 200: # Get the ComputerBios resource bios_url = response_system_url.dict['Bios']['@odata.id'] else: error_message = utils.get_extended_error(response_system_url) result = { 'ret': False, 'msg': "Url '%s' response error code %s \nerror_message: %s" % (system_url, response_system_url.status, error_message) } return result response_bios_url = REDFISH_OBJ.get(bios_url, None) if response_bios_url.status == 200: attribute = response_bios_url.dict['Attributes'] bios_attribute = {} if attribute_name in attribute.keys(): bios_attribute[attribute_name] = attribute[attribute_name] result = {'ret': True, 'msg': bios_attribute} else: result = { 'ret': False, 'msg': " No this attribute in the bios attribute" } elif response_bios_url.status == 400: result = { 'ret': False, 'msg': 'Not supported on this platform' } REDFISH_OBJ.logout() return result else: error_message = utils.get_extended_error(response_bios_url) result = { 'ret': False, 'msg': "Url '%s' response error code %s \nerror_message: %s" % (bios_url, response_bios_url.status, error_message) } return result except Exception as e: result = {'ret': False, 'msg': "error message %s" % e} finally: # Logout of the current session REDFISH_OBJ.logout() return result
def get_power_redundancy(ip, login_account, login_password): """Get power redundancy :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :returns: returns Get power redundant result when succeeded or error message when failed """ result = {} login_host = "https://" + ip # Connect using the BMC address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, timeout=utils.g_timeout, password=login_password, default_prefix='/redfish/v1', cafile=utils.g_CAFILE) # Login into the server and create a session try: REDFISH_OBJ.login(auth=utils.g_AUTH) except: traceback.print_exc() result = { 'ret': False, 'msg': "Please check the username, password, IP is correct\n" } return result # Get ServiceBase resource try: response_base_url = REDFISH_OBJ.get('/redfish/v1', None) # Get response_base_url if response_base_url.status == 200: chassis_url = response_base_url.dict['Chassis']['@odata.id'] else: error_message = utils.get_extended_error(response_base_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % ('/redfish/v1', response_base_url.status, error_message) } return result response_chassis_url = REDFISH_OBJ.get(chassis_url, None) if response_chassis_url.status == 200: rt_list_redundant = [] #Get power redundant for request in response_chassis_url.dict['Members']: request_url = request['@odata.id'] response_url = REDFISH_OBJ.get(request_url, None) if response_url.status == 200: # if chassis is not normal skip it if len(response_chassis_url.dict['Members']) > 1 and ( "Links" not in response_url.dict or "ComputerSystems" not in response_url.dict["Links"]): continue # if no Power property, skip it if "Power" not in response_url.dict: continue power_url = response_url.dict["Power"]['@odata.id'] response_power_url = REDFISH_OBJ.get(power_url, None) if response_power_url.status == 200: # if no Redundancy property, skip it if "Redundancy" not in response_power_url.dict: continue list_power_redundancy = response_power_url.dict[ "Redundancy"] for redundancy_item in list_power_redundancy: dict_power_redundant = {} for key in redundancy_item: if key == "RedundancySet": continue if key not in [ "Description", "@odata.context", "@odata.id", "@odata.type", "@odata.etag", "Links", "Actions", "RelatedItem" ]: dict_power_redundant[ key] = redundancy_item[key] rt_list_redundant.append(dict_power_redundant) else: error_message = utils.get_extended_error( response_power_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (power_url, response_power_url.status, error_message) } return result else: error_message = utils.get_extended_error(response_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (request_url, response_url.status, error_message) } return result if len(rt_list_redundant) > 0: result["ret"] = True result["entries"] = rt_list_redundant else: result = {'ret': False, 'msg': "No Redundancy found"} return result else: error_message = utils.get_extended_error(response_chassis_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (chassis_url, response_chassis_url.status, error_message) } return result except Exception as e: traceback.print_exc() result = {'ret': False, 'msg': 'exception msg %s' % e} return result finally: try: REDFISH_OBJ.logout() except: pass
def get_power_limit(ip, login_account, login_password): """Get power limit :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :returns: returns Get power limit result when succeeded or error message when failed """ result = {} login_host = "https://" + ip # Connect using the BMC address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, password=login_password, default_prefix='/redfish/v1', cafile=utils.g_CAFILE) # Login into the server and create a session try: REDFISH_OBJ.login(auth=utils.g_AUTH) except: result = {'ret': False, 'msg': "Please check the username, password, IP is correct\n"} return result # Get ServiceBase resource try: response_base_url = REDFISH_OBJ.get('/redfish/v1', None) # Get response_base_url if response_base_url.status == 200: chassis_url = response_base_url.dict['Chassis']['@odata.id'] else: error_message = utils.get_extended_error(response_base_url) result = {'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % ( '/redfish/v1', response_base_url.status, error_message)} return result response_chassis_url = REDFISH_OBJ.get(chassis_url, None) if response_chassis_url.status == 200: rt_list_limit = [] #Get power limit for request in response_chassis_url.dict['Members']: request_url = request['@odata.id'] response_url = REDFISH_OBJ.get(request_url, None) if response_url.status == 200: # if chassis is not normal skip it if len(response_chassis_url.dict['Members']) > 1 and "ComputerSystems" not in response_url.dict["Links"]: continue # if no Power property, skip it if "Power" not in response_url.dict: continue power_url = response_url.dict["Power"]['@odata.id'] response_power_url = REDFISH_OBJ.get(power_url, None) if response_power_url.status == 200: # if no PowerControl property, skip it if "PowerControl" not in response_power_url.dict: continue list_power_control = response_power_url.dict["PowerControl"] for control_item in list_power_control: if "PowerLimit" not in control_item: continue limit_item = {} limit_item = control_item["PowerLimit"] rt_list_limit.append(limit_item) else: error_message = utils.get_extended_error(response_power_url) result = {'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % ( power_url, response_power_url.status, error_message)} return result else: error_message = utils.get_extended_error(response_url) result = {'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % ( request_url, response_url.status, error_message)} return result if len(rt_list_limit) > 0: result["ret"] = True result["entries"] = rt_list_limit else: result = {'ret': False, 'msg': "No PowerLimit found"} return result else: error_message = utils.get_extended_error(response_chassis_url) result = {'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % ( chassis_url, response_chassis_url.status, error_message)} return result except Exception as e: result = {'ret': False, 'msg': 'exception msg %s' % e} return result finally: REDFISH_OBJ.logout()
def send_test_event(ip, login_account, login_password, eventid, message, severity): """Send test event :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :params eventid: event id :type eventid: string :params message: message of event :type message: string :params severity: severity of event :type severity: string :returns: returns Send test event result when succeeded or error message when failed """ #check paramater severitylist = ["OK", "Warning", "Critical"] if severity not in severitylist: result = { 'ret': False, "msg": "Severity scope in [OK,Warning,Critical],please check your input" } return result result = {} login_host = "https://" + ip # Connect using the BMC address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, password=login_password, default_prefix='/redfish/v1', cafile=utils.g_CAFILE) # Login into the server and create a session try: REDFISH_OBJ.login(auth=utils.g_AUTH) except: result = { 'ret': False, 'msg': "Please check the username, password, IP is correct\n" } return result # Get ServiceBase resource try: # Get /redfish/v1 response_base_url = REDFISH_OBJ.get('/redfish/v1', None) if response_base_url.status == 200: # Get /redfish/v1/EventService event_url = response_base_url.dict["EventService"]["@odata.id"] response_event_url = REDFISH_OBJ.get(event_url, None) if response_event_url.status == 200: # Check EventService Version EventService_Version = 130 #default version v1_3_0 EventService_Type = response_event_url.dict["@odata.type"] EventService_Type = EventService_Type.split('.')[-2] if EventService_Type.startswith('v'): EventService_Version = int( EventService_Type.replace('v', '').replace('_', '')) # Construct hearders and body to do post target_url = response_event_url.dict["Actions"][ "#EventService.SubmitTestEvent"]["target"] timestamp = datetime.datetime.now().strftime( '%Y-%m-%dT%H:%M:%S+08:00') headers = {"Content-Type": "application/json"} payload = {} if "@Redfish.ActionInfo" in response_event_url.dict["Actions"][ "#EventService.SubmitTestEvent"]: actioninfo_url = response_event_url.dict["Actions"][ "#EventService.SubmitTestEvent"]["@Redfish.ActionInfo"] response_actioninfo_url = REDFISH_OBJ.get( actioninfo_url, None) if (response_actioninfo_url.status == 200) and ("Parameters" in response_actioninfo_url.dict): for parameter in response_actioninfo_url.dict[ "Parameters"]: if ("Required" in parameter) and parameter["Required"]: if parameter["Name"] == "EventId": payload["EventId"] = eventid elif parameter["Name"] == "EventType": payload["EventType"] = "Alert" elif parameter["Name"] == "EventTimestamp": payload["EventTimestamp"] = timestamp elif parameter["Name"] == "Message": payload["Message"] = message elif parameter["Name"] == "MessageArgs": payload["MessageArgs"] = [] elif parameter["Name"] == "MessageId": payload["MessageId"] = "Created" elif parameter["Name"] == "Severity": payload["Severity"] = severity elif parameter["Name"] == "OriginOfCondition": payload["OriginOfCondition"] = event_url elif EventService_Version >= 130: payload["EventId"] = eventid payload["EventTimestamp"] = timestamp payload["Message"] = message payload["MessageArgs"] = [] payload["MessageId"] = "Created" payload["Severity"] = severity payload["OriginOfCondition"] = event_url elif EventService_Version >= 106: payload["EventId"] = eventid payload["EventType"] = "Alert" payload["EventTimestamp"] = timestamp payload["Message"] = message payload["MessageArgs"] = [] payload["MessageId"] = "Created" payload["Severity"] = severity payload["OriginOfCondition"] = event_url else: payload["EventId"] = eventid payload["EventType"] = "Alert" payload["EventTimestamp"] = timestamp payload["Message"] = message payload["MessageArgs"] = [] payload["MessageId"] = "Created" payload["Severity"] = severity response_send_event = REDFISH_OBJ.post(target_url, headers=headers, body=payload) if response_send_event.status == 200 or response_send_event.status == 204: result = {"ret":True,"msg":"Send event successsfully,event id is " + eventid \ + ",EventType:Alert,EventTimestamp:" + timestamp + ",Message:" + message \ + ",MessageArgs:[],MessageId:Created,Severity:" + severity\ + ",OriginOfCondition:" + event_url } return result else: error_message = utils.get_extended_error( response_send_event) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (target_url, response_send_event.status, error_message) } return result else: error_message = utils.get_extended_error(response_event_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (event_url, response_event_url.status, error_message) } return result else: error_message = utils.get_extended_error(response_base_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % ('/redfish/v1', response_base_url.status, error_message) } return result except Exception as e: result = {'ret': False, 'msg': "Exception msg %s" % e} return result finally: try: REDFISH_OBJ.logout() except: pass
def umount_virtual_media_from_rdoc(REDFISH_OBJ, remotecontrol_url, image): """ This function use the Lenovo OEM extensions to umount virtual media from RDOC, support 18D version of XCC. """ response_remotecontrol_url = REDFISH_OBJ.get(remotecontrol_url, None) if response_remotecontrol_url.status == 200: mount_image_url = response_remotecontrol_url.dict["MountImages"]["@odata.id"] else: error_message = utils.get_extended_error(response_remotecontrol_url) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( remotecontrol_url, response_remotecontrol_url.status, error_message)} return result # Get all virtual media url from mount image url response response_mount_images = REDFISH_OBJ.get(mount_image_url, None) if response_mount_images.status == 200: image_url_list = response_mount_images.dict["Members"] else: error_message = utils.get_extended_error(response_mount_images) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( mount_image_url, response_mount_images.status, error_message)} return result if image == "all": for image_url in image_url_list: image_url = image_url["@odata.id"] if image_url.split("/")[-1].startswith("RDOC"): # Umount all virtual media delete_image_response = REDFISH_OBJ.delete(image_url, None) if delete_image_response.status not in [200, 204]: error_message = utils.get_extended_error(delete_image_response) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( image_url, delete_image_response.status, error_message)} return result else: continue result = {"ret": True, "msg": "Umount all virtual media successfully."} return result # Umount user specify the virtual media else: for image_url in image_url_list: image_url = image_url["@odata.id"] get_image_response = REDFISH_OBJ.get(image_url, None) if get_image_response.status == 200: mount_iso_name = get_image_response.dict["Name"] if image == mount_iso_name: umount_iso_response = REDFISH_OBJ.delete(image_url, None) if umount_iso_response.status in [200, 204]: result = {'ret': True, 'msg': "Virtual media iso (%s) umount successfully" % (image)} return result else: error_message = utils.get_extended_error(umount_iso_response) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( image_url, umount_iso_response.status, error_message)} return result else: continue else: error_message = utils.get_extended_error(get_image_response) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( image_url, get_image_response.status, error_message)} return result result = {"ret": False, "msg": "Please check the iso name is correct and has been mounted."} return result
def clear_system_log(ip, login_account, login_password, system_id): """Clear system log :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :params system_id: ComputerSystem instance id(None: first instance, All: all instances) :type system_id: None or string :returns: returns clear system log result when succeeded or error message when failed """ result = {} login_host = 'https://' + ip try: # Connect using the BMC address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, password=login_password, default_prefix='/redfish/v1') # Login into the server and create a session REDFISH_OBJ.login(auth="session") except: result = { 'ret': False, 'msg': "Please check the username, password, IP is correct" } return result try: # Get response_base_url resource response_base_url = REDFISH_OBJ.get('/redfish/v1', None) if response_base_url.status == 200: managers_url = response_base_url.dict['Managers']['@odata.id'] else: error_message = utils.get_extended_error(response_base_url) result = { 'ret': False, 'msg': "Url '/redfish/v1' response Error code %s \nerror_message: %s" % (response_base_url.status, error_message) } return result # Get managers url resource response_managers_url = REDFISH_OBJ.get(managers_url, None) if response_managers_url.status == 200: manager_count = response_managers_url.dict['*****@*****.**'] else: error_message = utils.get_extended_error(response_managers_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % (managers_url, response_managers_url.status, error_message) } return result for i in range(manager_count): manager_x_url = response_managers_url.dict['Members'][i][ '@odata.id'] response_manager_x_url = REDFISH_OBJ.get(manager_x_url, None) if response_manager_x_url.status == 200: # Get the log server url log_services_url = response_manager_x_url.dict['LogServices'][ '@odata.id'] else: error_message = utils.get_extended_error( response_manager_x_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % (manager_x_url, response_manager_x_url.status, error_message) } return result # Get the response log server resource response_log_services_url = REDFISH_OBJ.get(log_services_url, None) if response_log_services_url.status == 200: members = response_log_services_url.dict['Members'] else: error_message = utils.get_extended_error( response_log_services_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % (log_services_url, response_log_services_url.status, error_message) } return result for member in members: log_url = member['@odata.id'] response_log_url = REDFISH_OBJ.get(log_url, None) if "Actions" in response_log_url.dict: if "#LogService.ClearLog" in response_log_url.dict[ "Actions"]: # Get the clear system log url clear_log_url = response_log_url.dict["Actions"][ "#LogService.ClearLog"]["target"] headers = {"Content-Type": "application/json"} # Build request body and send requests to clear the system log body = {} # get parameter requirement if ActionInfo is provided if "@Redfish.ActionInfo" in response_log_url.dict[ "Actions"]["#LogService.ClearLog"]: actioninfo_url = response_log_url.dict["Actions"][ "#LogService.ClearLog"]["@Redfish.ActionInfo"] response_actioninfo_url = REDFISH_OBJ.get( actioninfo_url, None) if (response_actioninfo_url.status == 200) and ( "Parameters" in response_actioninfo_url.dict): for parameter in response_actioninfo_url.dict[ "Parameters"]: if ("Name" in parameter) and ( "AllowableValues" in parameter): body[parameter["Name"]] = parameter[ "AllowableValues"][0] if not body: body = { "Action": "LogService.ClearLog" } #default body response_clear_log = REDFISH_OBJ.post(clear_log_url, headers=headers, body=body) if response_clear_log.status in [200, 204]: result = { 'ret': True, 'msg': "Clear log successfully" } else: error_message = utils.get_extended_error( response_clear_log) result = { 'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % (clear_log_url, response_clear_log.status, error_message) } except Exception as e: result = {'ret': False, 'msg': "error_message: %s" % (e)} finally: REDFISH_OBJ.logout() return result
def lenovo_umount_virtual_media(ip, login_account, login_password, image, mounttype): """Unmount virtual media, supporting both 18D and 19A version of Lenovo XCC. :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :param mounttype: Types of mount virtual media. :type mounttype:string :params image: This value shall specify the eject virtual media image mame :type image:string :returns: returns eject virtual media iso result when succeeded or error message when failed """ result = {} login_host = "https://" + ip # Login into the server try: # Connect using the address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, password=login_password, default_prefix='/redfish/v1', cafile=utils.g_CAFILE) REDFISH_OBJ.login(auth="basic") except: result = {'ret': False, 'msg': "Please check the username, password, IP is correct\n"} return result try: # Get ServiceRoot resource response_base_url = REDFISH_OBJ.get('/redfish/v1', None) # Get response_account_service_url if response_base_url.status == 200: account_managers_url = response_base_url.dict['Managers']['@odata.id'] else: error_message = utils.get_extended_error(response_base_url) result = {'ret': False, 'msg': " Url '/redfish/v1' response Error code %s \nerror_message: %s" % ( response_base_url.status, error_message)} return result response_managers_url = REDFISH_OBJ.get(account_managers_url, None) if response_managers_url.status == 200: # Get manager url form manager resource instance count = response_managers_url.dict['*****@*****.**'] for i in range(count): manager_url = response_managers_url.dict['Members'][i]['@odata.id'] response_manager_url = REDFISH_OBJ.get(manager_url, None) if response_manager_url.status == 200: # Get the virtual media url from the manger response virtual_media_url = response_manager_url.dict['VirtualMedia']['@odata.id'] # Get mount media iso url remotecontrol_url = response_manager_url.dict['Oem']['Lenovo']['RemoteControl']['@odata.id'] remotemap_url = response_manager_url.dict['Oem']['Lenovo']['RemoteMap']['@odata.id'] else: error_message = utils.get_extended_error(response_manager_url) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( manager_url, response_manager_url.status, error_message)} return result # Get the mount virtual media list response_virtual_media = REDFISH_OBJ.get(virtual_media_url, None) if response_virtual_media.status == 200: members_list = response_virtual_media.dict["Members"] else: error_message = utils.get_extended_error(response_virtual_media) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( virtual_media_url, response_virtual_media.status, error_message)} return result # for 19A, XCC predefined 10 members, so call umount function for 19A. otherwise, call function for 18D. if len(members_list) == 10: result = umount_virtual_media(REDFISH_OBJ, members_list, image) else: if mounttype == "Network": result = umount_all_virtual_from_network(REDFISH_OBJ, remotemap_url) else: result = umount_virtual_media_from_rdoc(REDFISH_OBJ, remotecontrol_url, image) else: error_message = utils.get_extended_error(response_managers_url) result = {'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % ( account_managers_url, response_managers_url.status, error_message)} except Exception as e: result = {'ret': False, 'msg': "error_message: %s" % (e)} finally: # Logout REDFISH_OBJ.logout() return result
def lenovo_add_alert_recipient(ip, login_account, login_password, setting_dict): """update bmc user global settings :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :params setting_dict: recipient setting :type setting_dict: string :returns: returns succeeded message or error message when failed """ result = {} # Connect using the BMC address, account name, and password # Create a REDFISH object login_host = "https://" + ip try: # Connect using the BMC address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, timeout=utils.g_timeout, password=login_password, default_prefix='/redfish/v1', cafile=utils.g_CAFILE, max_retry=3) # Login into the server and create a session REDFISH_OBJ.login(auth=utils.g_AUTH) except Exception as e: traceback.print_exc() result = { 'ret': False, 'msg': "Error_message: %s. Please check if username, password and IP are correct" % repr(e) } return result try: # Get ServiceBase resource response_base_url = REDFISH_OBJ.get('/redfish/v1', None) # Get Managers collection resource managers_url = response_base_url.dict['Managers']['@odata.id'] response_managers_url = REDFISH_OBJ.get(managers_url, None) # Get Manager resource manager_url = response_managers_url.dict['Members'][0]['@odata.id'] response_manager_url = REDFISH_OBJ.get(manager_url, None) # Get bmc recipients url if 'Oem' in response_manager_url.dict and 'Lenovo' in response_manager_url.dict[ 'Oem'] and 'Recipients' in response_manager_url.dict['Oem'][ 'Lenovo']: recipients_url = response_manager_url.dict['Oem']['Lenovo'][ 'Recipients']['@odata.id'] else: result = { 'ret': False, 'msg': "No support to add alert recipient." } return result # Get the Id used response_recipients_url = REDFISH_OBJ.get(recipients_url, None) id_used = [] for member in response_recipients_url.dict['Members']: id_used.append(member['@odata.id'].split("/")[-1]) index_id = setting_dict['Id'] # if Id is not specified, find first available Id. Otherwise, check the Id specified is being used or not if index_id == '': for i in range(1, 13): if str(i) not in id_used: index_id = str(i) break if index_id == '': result = { 'ret': False, 'msg': "No available Id to add alert recipient." } return result setting_dict['Id'] = index_id else: if index_id in id_used: result = { 'ret': False, 'msg': "Id %s has been used." % index_id } return result # POST setting info body to add one new recipient headers = {"Content-Type": "application/json"} response_add_recipient = REDFISH_OBJ.post(recipients_url, body=setting_dict, headers=headers) if response_add_recipient.status in [200, 201]: result = { "ret": True, "msg": "Add alert recipientsuccessfully, id is %s." % setting_dict['Id'] } return result else: error_message = utils.get_extended_error(response_add_recipient) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (recipients_url, response_add_recipient.status, error_message) } return result except Exception as e: traceback.print_exc() result = {'ret': False, 'msg': "Error message %s" % repr(e)} return result finally: # Logout of the current session try: REDFISH_OBJ.logout() except: pass
def set_manager_vlanid(ip, login_account, login_password, vlanid, vlanEnable): """Set BMC vlan id :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :params vlanid: vlan id by user specified :type vlanid: string :params vlanEnable: vlanenable type by user specified :type vlanEnable: string :returns: returns set manager vlanid result when succeeded or error message when failed """ result = {} login_host = "https://" + ip # Connect using the BMC address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, password=login_password, default_prefix='/redfish/v1') # Login into the server and create a session try: REDFISH_OBJ.login(auth="session") except: result = { 'ret': False, 'msg': "Please check the username, password, IP is correct" } return result try: # GET the managers url base_url = "/redfish/v1" response_base_url = REDFISH_OBJ.get(base_url, None) if response_base_url.status == 200: managers_url = response_base_url.dict['Managers']['@odata.id'] else: result = { 'ret': False, 'msg': "response base url Error code %s" % response_base_url.status } REDFISH_OBJ.logout() return result response_managers_url = REDFISH_OBJ.get(managers_url, None) if response_managers_url.status == 200: count = response_managers_url.dict["*****@*****.**"] for i in range(count): manager_url = response_managers_url.dict['Members'][i][ '@odata.id'] response_manager_url = REDFISH_OBJ.get(manager_url, None) # Get the ethernet interface url if response_manager_url.status == 200: ethernet_interface = response_manager_url.dict[ 'EthernetInterfaces']['@odata.id'] response_ethernet_interface = REDFISH_OBJ.get( ethernet_interface, None) if response_ethernet_interface.status == 200: for i in range(response_ethernet_interface. dict['*****@*****.**']): interface_url = response_ethernet_interface.dict[ 'Members'][i]['@odata.id'] if "NIC" in interface_url or "eth" in interface_url: # get etag to set If-Match precondition response_interface_url = REDFISH_OBJ.get( interface_url, None) if response_interface_url.status != 200: error_message = utils.get_extended_error( response_interface_url) result = { 'ret': False, 'msg': "Url '%s' get failed. response Error code %s \nerror_message: %s" % (interface_url, response_interface_url.status, error_message) } return result if "@odata.etag" in response_interface_url.dict: etag = response_interface_url.dict[ '@odata.etag'] else: etag = "" headers = {"If-Match": etag} ivlanid = int(vlanid) parameter = { "VLAN": { "VLANId": ivlanid, "VLANEnable": bool(int(vlanEnable)) } } response_interface_url = REDFISH_OBJ.patch( interface_url, body=parameter, headers=headers) if response_interface_url.status in [200, 204]: result = { 'ret': True, 'msg': "set BMC vlanid successfully" } else: error_message = utils.get_extended_error( response_interface_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % (interface_url, response_interface_url.status, error_message) } return result else: error_message = utils.get_extended_error( response_ethernet_interface) result = { 'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % (ethernet_interface, response_ethernet_interface.status, error_message) } return result else: error_message = utils.get_extended_error( response_manager_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % (manager_url, response_manager_url.status, error_message) } return result else: error_message = utils.get_extended_error(response_managers_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s \nerror_message: %s" % (managers_url, response_managers_url.status, error_message) } return result except Exception as e: result = {'ret': False, 'msg': "error_message: %s" % (e)} finally: # Logout of the current session REDFISH_OBJ.logout() return result
def lenovo_create_raid_volume(ip, login_account, login_password, system_id, raidid, volume_name, raid_type, volume_capacity, read_policy, write_policy, io_policy, access_policy, drive_cache_policy): """Create raid volume :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :params system_id: ComputerSystem instance id(None: first instance, All: all instances) :type system_id: None or string :params raidid: storage id :type raidid: string :params volume_name: name of the volume :type volume_name: string :params raid_type: raid type of the volume :type raid_type: string :params volume_capacity: capacity byte of the volume :type volume_capacity: int :params read_policy: read policy of the volume :type read_policy: string :params write_policy: write policy of the volume :type write_policy: string :params io_policy: io policy of the volume :type io_policy: string :params access_policy: access policy of the volume :type access_policy: string :params drive_cache_policy: drive cache policy of the volume :type drive_cache_policy: string :returns: returns storage inventory when succeeded or error message when failed """ result = {} login_host = "https://" + ip try: # Connect using the BMC address, account name, and password # Create a REDFISH object REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, password=login_password, default_prefix='/redfish/v1', cafile=utils.g_CAFILE) # Login into the server and create a session REDFISH_OBJ.login(auth=utils.g_AUTH) except: result = { 'ret': False, 'msg': "Please check the username, password, IP is correct" } return result storage_details = [] # GET the ComputerSystem resource system = utils.get_system_url("/redfish/v1", system_id, REDFISH_OBJ) if not system: result = { 'ret': False, 'msg': "This system id is not exist or system member is None" } REDFISH_OBJ.logout() return result target_raid_volumes_url = None for i in range(len(system)): system_url = system[i] response_system_url = REDFISH_OBJ.get(system_url, None) if response_system_url.status != 200: result = { 'ret': False, 'msg': "response_system_url Error code %s" % response_system_url.status } REDFISH_OBJ.logout() return result if "Storage" not in response_system_url.dict: continue #skip the invalid ComputeSystem that has no storage resource # GET the Storage resources from the ComputerSystem resource storage_url = response_system_url.dict["Storage"]["@odata.id"] response_storage_url = REDFISH_OBJ.get(storage_url, None) if response_storage_url.status != 200: result = { 'ret': False, 'msg': "response storage url Error code %s" % response_storage_url.status } REDFISH_OBJ.logout() storage_count = response_storage_url.dict["*****@*****.**"] if storage_count == 0: continue #skip the invalid ComputeSystem that has no storage resource # Collect all storage info first list_raid_id = [] list_raid_name = [] list_raid_drive_num = [] list_raid_volume_num = [] list_raid_volume_urls = [] for raid_index in range(0, storage_count): storage_x_url = response_storage_url.dict["Members"][raid_index][ "@odata.id"] response_storage_x_url = REDFISH_OBJ.get(storage_x_url, None) if response_storage_x_url.status != 200: result = { 'ret': False, 'msg': "response_storage_x_url code %s" % response_storage_x_url.status } REDFISH_OBJ.logout() return result Storage_id = response_storage_x_url.dict["Id"] Name = response_storage_x_url.dict["Name"] drive_num = len(response_storage_x_url.dict["Drives"]) volumes_url = response_storage_x_url.dict["Volumes"]["@odata.id"] response_volumes_url = REDFISH_OBJ.get(volumes_url, None) if response_volumes_url.status != 200: error_message = utils.get_extended_error(response_volumes_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (volumes_url, response_volumes_url.status, error_message) } return result volume_num = len(response_volumes_url.dict["Members"]) list_raid_id.append(Storage_id) list_raid_name.append(Name) list_raid_drive_num.append(drive_num) list_raid_volume_num.append(volume_num) list_raid_volume_urls.append(volumes_url) # Found the target storage when raidid is specified if raidid is not None: for raid_index in range(0, storage_count): if raidid == list_raid_id[ raid_index] or raidid == list_raid_name[raid_index]: if list_raid_drive_num[raid_index] == 0: result = { 'ret': False, 'msg': "There is no Drives on specified storage %s" % (raidid) } REDFISH_OBJ.logout() return result if list_raid_volume_num[raid_index] != 0: result = { 'ret': False, 'msg': "Volume has already been created on specified storage %s" % (raidid) } REDFISH_OBJ.logout() return result target_raid_volumes_url = list_raid_volume_urls[raid_index] break # Check whether only one raid storage can be configured when raidid is not specified. If multi-raid can be configured, raidid need to be specified else: for raid_index in range(0, storage_count): if list_raid_drive_num[raid_index] == 0: continue if list_raid_volume_num[raid_index] != 0: continue if target_raid_volumes_url is None: target_raid_volumes_url = list_raid_volume_urls[raid_index] else: result = { 'ret': False, 'msg': "There are multi-storage which can be configured. Please specified the raidid. raidid list: %s" % (str(list_raid_id)) } REDFISH_OBJ.logout() return result if target_raid_volumes_url is None: result = { 'ret': False, 'msg': "Failed to found storage that can be configured" } REDFISH_OBJ.logout() return result # USE POST to create a volume headers = {"Content-Type": "application/json"} parameter = { "Name": volume_name, "RAIDType": raid_type, "CapacityBytes": volume_capacity, "Oem": { "Lenovo": {} } } if read_policy is not None: parameter["Oem"]["Lenovo"]["ReadPolicy"] = read_policy if write_policy is not None: parameter["Oem"]["Lenovo"]["WritePolicy"] = write_policy if io_policy is not None: parameter["Oem"]["Lenovo"]["IOPolicy"] = io_policy if access_policy is not None: parameter["Oem"]["Lenovo"]["AccessPolicy"] = access_policy if drive_cache_policy is not None: parameter["Oem"]["Lenovo"]["DriveCachePolicy"] = drive_cache_policy response_create_volume = REDFISH_OBJ.post(target_raid_volumes_url, body=parameter, headers=headers) if response_create_volume.status in [200, 201]: rt_link = login_host + "/" + response_create_volume.dict[ "@odata.id"] id = rt_link.split("/")[-1] result = { "ret": True, "msg": "Create volume successfully, volume id is " + id + ", volume 's link is:" + rt_link } try: REDFISH_OBJ.logout() except: pass return result else: error_message = utils.get_extended_error(response_create_volume) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (target_raid_volumes_url, response_create_volume.status, error_message) } REDFISH_OBJ.logout() return result if target_raid_volumes_url is None: result = { 'ret': False, 'msg': "Failed to found storage that can be configured" } # Logout of the current session REDFISH_OBJ.logout() return result
def lenovo_ldap_certificate_add(ip, login_account, login_password, certfile): """ Add LDAP certificate :params ip: BMC IP address :type ip: string :params login_account: BMC user name :type login_account: string :params login_password: BMC user password :type login_password: string :params certfile: certificate file by user specified :type certfile: string :returns: returns get successful result when succeeded or error message when failed """ result = {} # check file existing if not os.path.exists(certfile): result = { 'ret': False, 'msg': "Specified file %s does not exist. Please check your certificate file path." % (certfile) } return result # Create a REDFISH object login_host = "https://" + ip REDFISH_OBJ = redfish.redfish_client(base_url=login_host, username=login_account, password=login_password, default_prefix='/redfish/v1') # Login into the server and create a session try: REDFISH_OBJ.login(auth="session") except: result = { 'ret': False, 'msg': "Please check the username, password, IP is correct\n" } return result try: # Get response_base_url response_base_url = REDFISH_OBJ.get('/redfish/v1', None) if response_base_url.status != 200: error_message = utils.get_extended_error(response_base_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % ('/redfish/v1', response_base_url.status, error_message) } return result # Use Oem API /redfish/v1/Managers/1/Oem/Lenovo/Security managers_url = response_base_url.dict['Managers']['@odata.id'] response_managers_url = REDFISH_OBJ.get(managers_url, None) if response_managers_url.status != 200: error_message = utils.get_extended_error(response_managers_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (managers_url, response_managers_url.status, error_message) } return result for request in response_managers_url.dict['Members']: # Access /redfish/v1/Managers/1 request_url = request['@odata.id'] response_url = REDFISH_OBJ.get(request_url, None) if response_url.status != 200: error_message = utils.get_extended_error(response_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (request_url, response_url.status, error_message) } return result # Check /redfish/v1/Managers/1/Oem/Lenovo/Security existing if "Oem" not in response_url.dict: continue if "Lenovo" not in response_url.dict["Oem"]: continue if "Security" not in response_url.dict["Oem"]["Lenovo"]: continue if "@odata.id" not in response_url.dict["Oem"]["Lenovo"][ "Security"]: continue # Access /redfish/v1/Managers/1/Oem/Lenovo/Security to confirm current index security_url = response_url.dict["Oem"]["Lenovo"]["Security"][ '@odata.id'] response_security_url = REDFISH_OBJ.get(security_url, None) if response_security_url.status != 200: error_message = utils.get_extended_error(response_security_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (security_url, response_security_url.status, error_message) } return result if "PublicKeyCertificates" not in response_security_url.dict: continue index = 1 for cert in response_security_url.dict["PublicKeyCertificates"]: if 'Subject' in cert and cert['Subject'] == 'LDAP_Server': index = index + 1 # Create request body target_url = security_url + "/Actions/LenovoSecurityService.ImportCertificate" request_body = { "Title": "ImportCertificate", "Service": "LDAP_Server", "ImportCertificateType": "TrustedCertificate", "Index": index } request_body["Target"] = target_url request_body["SignedCertificates"] = read_cert_file(certfile) # Perform post to add the certificate response_url = REDFISH_OBJ.post(target_url, body=request_body) if response_url.status not in [200, 201, 202, 204]: error_message = utils.get_extended_error(response_url) result = { 'ret': False, 'msg': "Url '%s' response Error code %s\nerror_message: %s" % (target_url, response_url.status, error_message) } else: result = { 'ret': True, 'msg': "The certificate has been added successfully. You must restart BMC to activate it." } try: REDFISH_OBJ.logout() except: pass return result # No LDAP certificate resource found result = {'ret': False, 'msg': 'LDAP certificate is not supported'} return result except Exception as e: result = {'ret': False, 'msg': 'exception msg %s' % e} return result finally: try: REDFISH_OBJ.logout() except: pass