def get_chassis_hardware_info(self, device, **kwargs): """Based on command "show chassis hardware" to get all hardware infomation :param BOOL force_get: *OPTIONAL* Set True will send command to get info every time. If set False, only first time send command to device. Default: False :param INT timeout: *OPTIONAL* Timeout to run "show chassis hardware" command :return: Return a DICT value have all hardware info, or return False """ func_name = self.tool.get_current_function_name() device.log(message=self.tool.print_title(func_name), level="INFO") options = {} options["force_get"] = kwargs.get("force_get", False) options["timeout"] = int(kwargs.get("timeout", self.default["cli_show_timeout"])) options["unittest"] = kwargs.get("unittest", None) # return immediatelly if have info in previous dev_keyword = str(device) if dev_keyword not in self.info["chassis_hardware_info"] or options["force_get"] is True: self.info["chassis_hardware_info"][dev_keyword] = dev.execute_cli_command_on_device( device=device, command="show chassis hardware", format="xml", channel="pyez", xml_to_dict=True, timeout=options["timeout"], ) device.log(message="{} return value:\n{}".format(func_name, self.tool.pprint(self.info["chassis_hardware_info"][dev_keyword])), level="INFO") return self.info["chassis_hardware_info"][dev_keyword]
def fetch_cpu_usage(self, device_handle): """ Function to fetch the Usage percentage of the CPU using the command show system visibility cpu from JDM Python Example: _cpu_usage_ = fetch_cpu_usage(device_handle=r0_handle) Robot Example: ${cpu_usage} Fetch CPU Usage device_handle=${r0_handle} :params str device_handle: **REQUIRED** Device Handle of JDM :return: Dictionary of Logical CPU as keys and percentage usage as values """ try: _cmd_ = "show system visibility cpu" _output_ = execute_cli_command_on_device(device=device_handle, command=_cmd_) _cpu_usage_flag_ = False _return_dict_ = {} _found_ = False for _row_ in _output_.split("\n"): _match_ = re.match(r".*CPU\s+Usages.*", _row_) if _match_ is not None: _cpu_usage_flag_ = True continue _match_ = re.match(r".*CPU\s+Pinning.*", _row_) if _match_ is not None: _cpu_usage_flag_ = False continue if _cpu_usage_flag_ is True: _match_ = re.match(r"(\d+)\s+(\S+)", _row_) if _match_ is not None: _return_dict_[int(_match_.group(1))] = float( _match_.group(2)) _found_ = True if _found_ is False: raise Exception("No CPU Usage Information found in output") else: return True, _return_dict_ except Exception as _exception_: raise Exception("Error: %s: %s" % (type(_exception_), _exception_))
def fetch_vnf_list_from_config(self, device_handle): """ Python function to get a list of VNF names configured on the JDM Python Example: _vnf_list_ = fetch_vnf_list_from_config(device_handle=_jdm_) Robot Example: ${vnf_list} Fetch VNF List From Config device_handle=${jdm} :param str device_handle: **REQUIRED** Device Handle of JDM :returns: List containing the VNF names """ try: _return_list_ = [] t.log("INFO", "Fetching Configured VNF List on device: %s" % device_handle) _cmd_ = "show configuration | display set | match virtual-network-functions.*image" _output_ = execute_cli_command_on_device(device=device_handle, command=_cmd_) for _row_ in _output_.split("\n"): _match_ = re.match( r"set\s+virtual-network-functions\s+(\S+)\s+.*", _row_) if _match_ is not None: _return_list_.append(_match_.group(1)) return _return_list_ except Exception as _exception_: t.log( "ERROR", "Exception in fetch_vnf_list_from_config: %s : %s" % (type(_exception_), _exception_))
def get_chassis_fpc_info(self, device, **kwargs): """Based on cmd "show chassis fpc pic-status" to get all pic information :param BOOL force_get: *OPTIONAL* set True will send cmd to get info every time. Or set False to get info from previous. Default: False :param INT timeout: *OPTIONAL* get info timeout. Default: {} :return: Return a DICT value have all pic info, or return False """.format(self.default["cli_show_timeout"]) func_name = self.tool.get_current_function_name() device.log(message=self.tool.print_title(func_name), level="INFO") options = {} options["force_get"] = kwargs.get("force_get", False) options["timeout"] = int(kwargs.get("timeout", self.default["cli_show_timeout"])) # return immediatelly if have info in previous dev_keyword = str(device) if dev_keyword in self.info["chassis_fpc_pic_info"] and options["force_get"] is False: device.log(message="{} return value:\n{}".format(func_name, self.tool.pprint(self.info["chassis_fpc_pic_info"][dev_keyword])), level="INFO") return self.info["chassis_fpc_pic_info"][dev_keyword] self.info["chassis_fpc_pic_info"][dev_keyword] = dev.execute_cli_command_on_device( device=device, command="show chassis fpc pic-status", format="xml", channel="pyez", xml_to_dict=True, timeout=options["timeout"], ) device.log(message="{} return value:\n{}".format(func_name, self.tool.pprint(self.info["chassis_fpc_pic_info"][dev_keyword])), level="INFO") return self.info["chassis_fpc_pic_info"][dev_keyword]
def _common_get_processing(self, device, cmd_keyword, kwargs): """Common processing to handle device xml response For "show system security-profile ..." cmds, device response almost have same data structure. This method extract common processing to treat these response :param STR cmd_keyword: **REQUIRED** feature command keyword. :param DICT kwargs: **REQUIRED** more_options :return: Return a LIST contain all entries or TEXT response """ options = {} options["more_options"] = kwargs.pop('more_options', None) options["return_mode"] = str(kwargs.pop("return_mode", None)).strip().upper() options["timeout"] = int( kwargs.pop("timeout", self.default["CLI_COMMIT_TIMEOUT"])) cmd_element = [] cmd_element.append( "show system security-profile {}".format(cmd_keyword)) if options["more_options"]: cmd_element.append(options["more_options"]) if options["return_mode"] == "TEXT": response_format = "text" else: response_format = "xml" response = dev.execute_cli_command_on_device( device=device, command=" ".join(cmd_element), channel="pyez", format=response_format, timeout=options["timeout"], ) if options["return_mode"] == "TEXT": return response response = self.xml.strip_xml_response( self.xml.xml_to_pure_dict(response), return_list=True) if cmd_keyword == "nat-interface-port-ol": cmd_keyword = "nat-interface-po" main_path_keyword = "security-profile-{}-information".format( cmd_keyword) all_entry_list = [] for item in response: info = {} for keyword in item: if keyword != main_path_keyword: info[self.tool.underscore_and_lowercase_transit( keyword)] = str(item[keyword]) for entry in self.tool.set_element_list( item[main_path_keyword]["security-profile-information"]): for keyword in entry: info_keyword = self.tool.underscore_and_lowercase_transit( keyword) info[info_keyword] = str(entry[keyword]) all_entry_list.append(copy.deepcopy(info)) return all_entry_list
def change_mek(device_handle, current_pswd, new_pswd, **kwargs): """ :param device_handle: **REQUIRED** device object :param current_pswd: ***REQUIRED*** Current Master Encryption Password :param new_pswd: ***REQUIRED*** New Master Encryption Password :param node: ***OPTIONAL*** can be 'node0', 'node1' or 'both' if device is in HA. Default is both. :return True if Master Encryption Password is set/changed successfully Python Examples: change_mek(srx0, current_pswd=ddhhkkslwjcngh!!!, new_pswd=xkjdfkejfns$@!) change_mek(srx0, current_pswd=ddhhkkslwjcngh!!!, new_pswd=xkjdfkejfns$@!, node=node0) Robot Examples: Change Mek ${srx0} current_pswd=ddhhkcngh!!! new_pswd=xkjdfke$@! Change Mek ${srx0} current_pswd=ddhhkjcngh!!! new_pswd=xkjdfns$@! node=node0 """ ha_dev = HA() result = False chassis_cluster = _check_chassis_cluster(device_handle) cmd = 'request security tpm master-encryption-password set plain-text-password' error_msgs = ["error: Password entered does not match with old password", "error: Passwords do not match", "Recommend at least length 12 and use of 3 character classes"] flag = 1 if new_pswd == current_pswd else 0 if flag: raise Exception("error: Password entered is same as old password.") if chassis_cluster: node = kwargs.get('node', 'both') node_list = ['node0', 'node1'] if node == 'both' else [node] for node in node_list: ha_dev.execute_cli_on_node(device=device_handle, node=node, command=cmd, pattern="password: "******"password: "******"password: "******"successfully generated", str(response).lower()): result = True elif str(response) in error_msgs: raise Exception(str(response)) else: raise Exception("Master Encryption Password could not be changed") else: dev.execute_cli_command_on_device(device=device_handle, command=cmd, pattern="password: "******"password: "******"password: "******"successfully generated", str(response).lower()): result = True elif str(response) in error_msgs: raise Exception(str(response)) else: raise Exception("Master Encryption Password could not be changed") return result
def set_mek(device_handle, new_pswd, **kwargs): """ :param device_handle: **REQUIRED** device object :param new_pswd: ***REQUIRED*** New Master Encryption Password :param node: ***OPTIONAL*** can be 'node0', 'node1' or 'both' if device is in HA. Default is both. :return True if Master Encryption Password is set/changed successfully Python Examples: set_mek(srx0, new_pswd=xkjdfkejfns$@!) set_mek(srx0, new_pswd=xkjdfkejfns$@!, node=node0) Robot Examples: Set Mek ${srx0} new_pswd=xkjdfkejfns$@! Set Mek ${srx0} new_pswd=xkjdfkejfns$@! node=node0 """ ha_dev = HA() chassis_cluster = _check_chassis_cluster(device_handle) cmd = 'request security tpm master-encryption-password set plain-text-password' if chassis_cluster: node = kwargs.get('node', 'both') node_list = ['node0', 'node1'] if node == 'both' else [node] for node in node_list: ha_dev.execute_cli_on_node(device=device_handle, node=node, command=cmd, pattern="password: "******"password: "******"successfully", (str(response)).lower()): result = True elif re.search("error: Passwords do not match", str(response)): raise Exception("error: Passwords do not match") elif re.search("Recommend at least length 12 and use of 3 character classes", str(response)): raise Exception("error: Password does not meet required criteria.") else: raise Exception("Master Encryption Password could not be set") else: dev.execute_cli_command_on_device(device=device_handle, command=cmd, pattern="password: "******"password: "******"successfully", (str(response)).lower()): result = True elif re.search("error: Passwords do not match", str(response)): raise Exception("error: Passwords do not match") elif re.search("Recommend at least length 12 and use of 3 character classes", str(response)): raise Exception("error: Password does not meet required criteria. " "Recommend at least length 12 and use of 3 character classes") else: raise Exception("Master Encryption Password could not be set") return result
def waiting_for_pic_online(self, device, **kwargs): """Waiting a while to make sure wantted pic online Based on cmd "show chassis fpc pic-status", this method checking wantted pic whether online. This is useful for device reboot :param STR|LIST|TUPLE except_component: **OPTIONAL** As default, all device component must online, but you can give one or more component name here to avoid checking. For example: ``` Slot 0 Online SRX5k SPC II PIC 0 Offline SPU Cp PIC 1 Online SPU Flow PIC 2 Online SPU Flow PIC 3 Offline SPU Flow Slot 2 Online SRX5k IOC II PIC 0 Online 10x 10GE SFP+ ``` Above output will create an internal offline list: ["SLOT 0 PIC 0", "SLOT 0 PIC 3", "PIC 0", "PIC 3"], you can list these keywords in this option to skip them. This means you can just skip "PIC 0" for all SLOT, or set "SLOT 0 PIC 0" for specific PIC. By the way, component keyword is case insensitive, this means keyword "pic 0", "PIC 0", or "Slot 0 Pic 0" all match above output For IOC 3, 2 PICs always offline, and this method will skip them automatically. :param INT check_counter: **OPTIONAL** how many times to checking device status. Default: 10 :param INT check_interval: **OPTIONAL** waiting interval between checking. Default: 30 :param INT timeout: **OPTIONAL** timeout to get device response. :return: True/False. Or raise ValueError for invalid option :example: status = self.waiting_for_pic_online(device=r0, except_component=("PIC 0", "Slot 0", "Slot 1 PIC 2"), check_counter=10, check_interval=60) """ func_name = self.tool.get_current_function_name() device.log(message=self.tool.print_title(func_name), level="INFO") options = {} options["except_component"] = kwargs.get("except_component", ()) options["check_counter"] = int(kwargs.get("check_counter", 10)) options["check_interval"] = int(kwargs.get("check_interval", 30)) options["timeout"] = int(kwargs.get("timeout", self.default["cli_show_timeout"])) if isinstance(options["except_component"], str): options["except_component"] = (options["except_component"], ) checking_result = False get_pic_status_cmd = "show chassis fpc pic-status" for index in range(1, options["check_counter"] + 1): ioc3_component_cnt = 0 device.log(message="Index {:02d}: FPC PIC status check...".format(index), level="INFO") response = dev.execute_cli_command_on_device( device=device, command=get_pic_status_cmd, channel="pyez", format="xml", xml_to_dict=True, timeout=options["timeout"], ) if response is False: device.log( message="cannot got FPC PIC status from device, waiting {} secs for next checking...".format(options["check_interval"]), level="INFO", ) time.sleep(options["check_interval"]) continue if "multi-routing-engine-results" in response: response = response["multi-routing-engine-results"]["multi-routing-engine-item"] if not isinstance(response, (list, tuple)): device.log( message="only one node response occurred, waiting {} secs for next checking...".format(options["check_interval"]), level="INFO", ) time.sleep(options["check_interval"]) continue # SA always a DICT, but HA is a LIST that contain 2 nodes' response if not isinstance(response, (list, tuple)): response = [response, ] offline_component_list = [] for node_item in response: try: fpc_list = node_item["fpc-information"]["fpc"] except (TypeError, KeyError): offline_component_list.append("FPC") device.log(message="No FPC status contained.", level="INFO") continue if not isinstance(fpc_list, (list, tuple)): fpc_list = [fpc_list, ] for fpc in fpc_list: fpc_state = fpc["state"] if "state" in fpc else None fpc_slot = fpc["slot"] if "slot" in fpc else "Unknown" fpc_description = fpc["description"] if "description" in fpc else "Unknown" pic_list = fpc["pic"] if "pic" in fpc else None fpc_name = "SLOT {}".format(fpc_slot) if fpc_state is None or not re.match(r"Online", fpc_state.strip(), re.I): if fpc_name not in offline_component_list: offline_component_list.append(fpc_name) continue if re.search(r"\s+IOC3\s+", fpc_description): device.log(message="'{}' card found on '{}'.".format(fpc_description, fpc_name), level="INFO") ioc3_component_cnt += 1 if not pic_list: device.log(message="no PIC infomation for FPC '{}'".format(fpc_description), level="INFO") continue if not isinstance(pic_list, (list, tuple)): pic_list = [pic_list, ] for pic in pic_list: pic_slot = pic["pic-slot"] if "pic-slot" in pic else "Unknown" pic_state = pic["pic-state"] if "pic-state" in pic else None # pic_type = pic["pic-type"] if "pic-type" in pic else "Unknown" pic_name = "{} PIC {}".format(fpc_name, pic_slot) if pic_state is None or not re.match(r"Online", pic_state.strip(), re.I): if pic_name not in offline_component_list: offline_component_list.append(pic_name) if offline_component_list: device.log(message="OFFLINE component: {}".format(offline_component_list), level="INFO") for item in options["except_component"]: item = item.upper() if item in offline_component_list: del offline_component_list[offline_component_list.index(item)] # IOC3 card always have 2 offline PIC if not offline_component_list or len(offline_component_list) == ioc3_component_cnt * 2: checking_result = True device.log(message="All FPC and PIC onlined...", level="INFO") break device.log(message="Waiting '{}' secs for next component checking...".format(options["check_interval"]), level="INFO") time.sleep(options["check_interval"]) device.log(message="{} return value: {}".format(func_name, checking_result), level="INFO") return checking_result
def execute_command_on_vnf(self, tag, vnf_name, cmd, console=False, mode="SHELL"): """ Function to execute a command on a VNF that is either of type linux / junos. Python Example: _cmd_shell_ = "uptime" _cmd_cli_ = "show version" _cmd_config_ = "show system" _response_ = execute_command_on_vnf(tag='r0', vnf_name='centos', cmd=_cmd_shell_, mode='shell', console=False) _response_ = execute_command_on_vnf(tag='r0', vnf_name='vsrx', cmd=_cmd_cli_, mode='cli', console=False) _response_ = execute_command_on_vnf(tag='r0', vnf_name='vjunos0', cmd=_cmd_config_, mode='config', console=False) _response_ = execute_command_on_vnf(tag='r0', vnf_name='centos', cmd=_cmd_shell_, mode='shell', console=True) _response_ = execute_command_on_vnf(tag='r0', vnf_name='vsrx', cmd=_cmd_cli_, mode='cli', console=True) _response_ = execute_command_on_vnf(tag='r0', vnf_name='vjunos0', cmd=_cmd_config_, mode='config', console=True) Robot Example: ${cmd_shell} Set Variable uptime ${cmd_cli} Set Variable show version ${cmd_config} Set Variable show system ${response} Execute Command On VNF tag=r0 vnf_name=centos cmd=${cmd_shell} mode=shell console=${false} ${response} Execute Command On VNF tag=r0 vnf_name=vsrx cmd=${cmd_cli} mode=cli console=${false} ${response} Execute Command On VNF tag=r0 vnf_name=vjunos0 cmd=${cmd_config} mode=config console=${false} ${response} Execute Command On VNF tag=r0 vnf_name=centos cmd=${cmd_shell} mode=shell console=${true} ${response} Execute Command On VNF tag=r0 vnf_name=vsrx cmd=${cmd_cli} mode=cli console=${true} ${response} Execute Command On VNF tag=r0 vnf_name=vjunos0 cmd=${cmd_config} mode=config console=${true} :param str tag: **REQUIRED** Name of the resource on which this VNF is hosted :param str vnf_name: **REQUIRED** Name of the VNF :param str cmd: **REQUIRED** Command to be executed :param bool console: **OPTIONAL** Set to True if command is to be executed on console to vnf, else to False for ssh Default: False :param str mode: **OPTIONAL** Mode of execution shell/cli/config. For linux VNFs, only shell is valid value and others apply for junos type VNFs. It is up to the user to invoke this function accordingly Default: shell """ try: self.__log_info__( "Executing Command: %s in Mode: %s on VNF: %s on %s" % (cmd, mode, vnf_name, tag)) _device_handle_ = None if console is True: _status_, _device_handle_ = self.get_vnf_handle(tag, vnf_name, mode="console") else: _status_, _device_handle_ = self.get_vnf_handle(tag, vnf_name, mode="ssh") except Exception as _exception_: raise Exception("Exception caught: %s: %s" % (type(_exception_), _exception_)) mode = mode.lower() _expected_modes_ = ["shell", "cli", "config"] if mode not in _expected_modes_: raise Exception("Unsupported value for mode: %s" % mode) try: if mode == "shell": _resp_ = execute_shell_command_on_device( device=_device_handle_, command=cmd) elif mode == "cli": _resp_ = execute_cli_command_on_device(device=_device_handle_, command=cmd) elif mode == "config": _resp_ = execute_config_command_on_device( device=_device_handle_, command_list=cmd) return True, _resp_ except Exception as _exception_: raise Exception("Exception caught: %s: %s" % (type(_exception_), _exception_))
def fetch_route_instance_entry(self, device, **kwargs): """Get route instance entries This method use basic command "show route instance". More options will be tailed to basic command. HighEnd/LowEnd, SA/HA are supported. According to option "return_mode", method can return a LIST contain all flat entries or just plain-text :param STR name: *OPTIONAL* Instance name. default: None :param STR more_options: *OPTIONAL* String will tailed to base cmd. Default: None :param str return_mode: *OPTIONAL* response format that one of "TEXT", "ENTRY_LIST" or "FLAT_DICT. Default: ENTRY_LIST :param int timeout: *OPTIONAL* timeout to get command response. default: 300 :return: If option "return_mode" is 'TEXT', just return device response without any more process. if option 'return_mode' is 'ENTRY_LIST' (default), return a LIST contain all entries. No entry found just return empty LIST :example: [ { 'instance_name': 'master', 'instance_type': 'forwarding', 'instance_rib': [ { 'irib_name': 'inet.0', 'irib_active_count': '22', 'irib_holddown_count': '0', 'irib_hidden_count': '0' }, { 'irib_name': 'inet6.0', 'irib_active_count': '7', 'irib_holddown_count': '0', 'irib_hidden_count': '0' } ] } ] if option 'return_mode' is 'FLAT_DICT', return a LIST contain all entries like below: """ func_name = self.tool.get_current_function_name() device.log(message=self.tool.print_title(func_name), level="INFO") options = {} options["name"] = kwargs.pop('name', None) options["more_options"] = kwargs.pop('more_options', None) options["return_mode"] = str(kwargs.pop("return_mode", "ENTRY_LIST")).strip().upper() options["print_response"] = kwargs.pop("print_response", True) options["timeout"] = int( kwargs.pop('timeout', self.default['cli_show_timeout'])) if options["return_mode"] not in ("TEXT", "ENTRY_LIST"): raise ValueError( "'return_mode' must be 'ENTRY_LIST' or 'TEXT', not '{}'". format(options["return_mode"])) if options["return_mode"] == "ENTRY_LIST": response_format = "xml" else: response_format = "text" # combine options to basic command cmd_elements = [] cmd_elements.append("show route instance") if options["name"]: cmd_elements.append(options["name"]) if options["more_options"]: cmd_elements.append(options["more_options"]) # get route instance entries response = dev.execute_cli_command_on_device( device=device, command=" ".join(cmd_elements), channel="pyez", format=response_format, timeout=options["timeout"], ) # if user want get "text" mode response, just return here if options["return_mode"] == "TEXT": device.log(message="{} return value:\n{}".format( func_name, response), level="INFO") return response if response is False: return False response = self.xml.strip_xml_response( self.xml.xml_to_pure_dict(response), return_list=False) instance_core_list = self.tool.set_element_list( response["instance-information"]["instance-core"]) route_instance_entry_list = [] # HE/LE, SA/HA device all have same structure response for instance_core in instance_core_list: info = {} for keyword in instance_core: underscore_keyword = self.tool.underscore_and_lowercase_transit( keyword) # instance_rib have another argument list if underscore_keyword == "instance_rib": rib_list = [] instance_core[keyword] = self.tool.set_element_list( instance_core[keyword]) for rib_entry in instance_core[keyword]: rib_info = {} for rib_keyword in rib_entry: rib_underscore_keyword = self.tool.underscore_and_lowercase_transit( rib_keyword) rib_info[rib_underscore_keyword] = str( rib_entry[rib_keyword]) rib_list.append(rib_info) info[underscore_keyword] = rib_list continue info[underscore_keyword] = str(instance_core[keyword]) route_instance_entry_list.append(info) flat_entry_list = [] for entry in route_instance_entry_list: info = {} for keyword in entry: if keyword != "instance_rib": info[keyword] = entry[keyword] if "instance_rib" in entry: for instance_rib_entry in entry["instance_rib"]: for keyword in instance_rib_entry: info["instance_rib_{}".format( keyword)] = instance_rib_entry[keyword] flat_entry_list.append(copy.deepcopy(info)) else: flat_entry_list.append(copy.deepcopy(info)) if options["print_response"] is True: device.log(message="return value:\n{}".format( self.tool.pprint(flat_entry_list)), level="INFO") return flat_entry_list
def get_ioc_slot_number(self, device, **kwargs): """Get IOC slot id This method based on command "show chassis fpc pic-status" and return ioc's slot number. This is useful to enable/disable services-offload configuration later. :param INT|STR|LIST except_slot_number: *OPTIONAL* Given slot number(s) will not added to list. Default: None :param INT|STR largest_slot_number: *OPTIONAL* For HA topology. Ignore slot id greater or equal given slot number. Default: 6 :param BOOL force_get: *OPTIONAL* If set True, will get ioc_slot_number list every time. Set False will return ioc_slot_number from cache. **IMPORTANT: If 'force_get' is False, this method will return ioc_slot_number from cache, it means will not remove 'except_slot_number'.** **If need except more slot number, pls set 'force_get'=True** Default: False :return: Return a LIST that contain all IOC's slot number """ func_name = self.tool.get_current_function_name() device.log(message=self.tool.print_title(func_name), level="INFO") options = {} options["except_slot_number"] = kwargs.pop("except_slot_number", []) options["largest_slot_number"] = int( kwargs.pop("largest_slot_number", 6)) options["force_get"] = self.tool.check_boolean( kwargs.pop("force_get", False)) if not isinstance(options["except_slot_number"], (list, tuple)): options["except_slot_number"] = (options["except_slot_number"], ) if len(options["except_slot_number"]) != 0 \ or func_name not in self.hidden_info \ or str(device) not in self.hidden_info[func_name]: options["force_get"] = True if options["force_get"] is False and str( device) in self.hidden_info[func_name]: return_value = self.hidden_info[func_name][str(device)] device.log(message="{} return value: {}".format( func_name, return_value), level="INFO") return return_value ioc_number_sets = set() response = dev.execute_cli_command_on_device( device=device, command="show interface terse", channel="text", format="text") for line in response.splitlines(): match = re.search(r"xe\-(\d+)\/\d+\/\d+\s+", line) if match and int(match.group(1)) <= options["largest_slot_number"]: ioc_number_sets.add(int(match.group(1))) for except_number in options["except_slot_number"]: except_number = int(except_number) if except_number in ioc_number_sets: ioc_number_sets.remove(except_number) return_value = list(ioc_number_sets) if func_name not in self.hidden_info: self.hidden_info[func_name] = {} self.hidden_info[func_name][str(device)] = return_value device.log(message="{} return value: {}".format( func_name, return_value), level="INFO") return return_value
def set_services_offload(self, device, ioc_slot_number, **kwargs): """Enable/Disable services offload on FPC :param INT|STR|LIST ioc_slot_number: *MANDATORY* IOC slot number or number list to enable/disable services-offload. :param STR action: *OPTIONAL* Enable or Disable services-offload on given ioc slot number(s). Default: Enable :param STR reboot_mode: *OPTIONAL* One of "None", "Reboot", "Gracefully", "Immediately" or "Soft". Case-insensitive. Default: None - None: Do not reboot - Reboot: Reboot device by command: "request system reboot" - Gracefully: by command: "restart chassis-control gracefully" - Immediately: by command: "restart chassis-control immediately" - Soft: by command: "restart chassis-control soft" :param BOOL waiting_for_pic_online: *OPTIONAL* Waiting for all PIC online after device reboot. This option only for option 'reboot_mode' is not None. Default: True :param STR|LIST waiting_for_pic_online_except_component: *OPTIONAL* Set security.chassis.chassis.waiting_for_pic_online for detail. Default: () :param INT|STR waiting_for_pic_online_check_interval: *OPTIONAL* Check interval (sec) during waiting_for_pic_online. Default: 30 :param INT|STR waiting_for_pic_online_check_counter: *OPTIONAL* Check counter (sec) during waiting_for_pic_online. Default: 20 :return: True/False for services-offload enabled/disabled for given ioc_slot_number. """ func_name = self.tool.get_current_function_name() device.log(message=self.tool.print_title(func_name), level="INFO") options = {} options["ioc_slot_number"] = ioc_slot_number options["action"] = str(kwargs.pop("action", "Enable")).upper() options["reboot_mode"] = str(kwargs.pop("reboot_mode", None)).lower() options["waiting_for_pic_online"] = self.tool.check_boolean( kwargs.pop("waiting_for_pic_online", True)) options["waiting_for_pic_online_except_component"] = kwargs.pop( "waiting_for_pic_online_except_component", ()) options["waiting_for_pic_online_check_interval"] = int( kwargs.pop("waiting_for_pic_online_check_interval", 30)) options["waiting_for_pic_online_check_counter"] = int( kwargs.pop("waiting_for_pic_online_check_counter", 20)) if not isinstance(options["ioc_slot_number"], (list, tuple)): options["ioc_slot_number"] = (options["ioc_slot_number"], ) if options["action"] not in ("ENABLE", "DISABLE"): raise ValueError( "{}: option 'action' must be enable or disable but got '{}'". format(func_name, options["action"])) if options["reboot_mode"] not in ("none", "reboot", "gracefully", "immediately", "soft"): raise ValueError( "{}: option 'reboot_mode' must be 'none', 'reboot', 'gracefully', 'immediately' or 'soft'" .format(func_name)) action_str = "set" if options["action"] == "ENABLE" else "delete" cmds = [] for number in options["ioc_slot_number"]: cmds.append("{} chassis fpc {} np-cache".format( action_str, number)) status = dev.execute_config_command_on_device(device=device, command=cmds, commit=True) if options["reboot_mode"] == "none": device.log(message="{} return value: {}".format(func_name, status), level="INFO") return status elif options["reboot_mode"] == "reboot": if device.is_ha() is True: status = dev.reboot_device(device=device, timeout=1200, all=True) else: status = dev.reboot_device(device=device, timeout=1200) else: status = dev.execute_cli_command_on_device( device=device, channel="text", format="text", command="restart chassis-control {}".format( options["reboot_mode"]), ) if options["waiting_for_pic_online"] is False: device.log(message="{} return value: {}".format(func_name, status), level="INFO") return status time.sleep(10) status = self.chassis.waiting_for_pic_online( device=device, except_component=options[ "waiting_for_pic_online_except_component"], check_interval=options["waiting_for_pic_online_check_interval"], check_counter=options["waiting_for_pic_online_check_counter"], ) device.log(message="{} return value: {}".format(func_name, status), level="INFO") return status
def check_vmhost(device, **kwargs): """checking vmhost based device for SRX There are 2 ways to upgrade or ISSU upgrade device, one is "request system software ..." and the other is "request vmhost software ...". This method checking device hardware and tell you keyword of 'system' or 'vmhost'. Return: 'system' or 'vmhost' """ func_name = TOOL.get_current_function_name() dev_fingerprint = str(device) vmhost_keyword_list = (re.compile(r"RE-2000x6", re.I), ) options = {} options["force"] = TOOL.check_boolean(kwargs.pop("force", False)) if func_name not in RUNTIME: RUNTIME[func_name] = {} if dev_fingerprint not in RUNTIME[func_name]: RUNTIME[func_name][dev_fingerprint] = None if options["force"] is False and RUNTIME[func_name][ dev_fingerprint] is not None: return RUNTIME[func_name][dev_fingerprint] cmd = "show chassis hardware" if device.is_ha() is True: cmd += " node 0" component_list = dev.execute_cli_command_on_device(device=device, channel="pyez", format="xml", xml_to_dict=True, command=cmd) if device.is_ha() is True: component_list = component_list["multi-routing-engine-results"][ "multi-routing-engine-item"] # strip root tag then all sub chassis components should be list or tuple component_list = component_list["chassis-inventory"]["chassis"][ "chassis-module"] if not isinstance(component_list, (tuple, list)): component_list = (component_list, ) return_value = "system" for component in component_list: if "name" not in component or not re.match( r"Routing Engine", str(component["name"]).strip()): continue for pattern in vmhost_keyword_list: if re.search(pattern, component["description"]): return_value = "vmhost" break if return_value == "vmhost": break RUNTIME[func_name][dev_fingerprint] = return_value device.log(message="{} return value: {}".format(func_name, return_value), level="INFO") return return_value
def get_interface_hardware_address(device, interface_name, **kwargs): """Get device interface MAC address This function get interface MAC address from Linux host or SRX device. :param STR platform: *OPTIONAL* Device platform string such as 'Linux' or 'srx'. Set None to get platform automatically. default: None :param BOOL uppercase: *OPTIONAL* Uppercase hardware address and return. default: False :return: Return interface MAC address or raise RuntimeException """ func_name = TOOL.get_current_function_name() device.log(message=TOOL.print_title(func_name), level="INFO") options = {} options["platform"] = kwargs.pop("platform", None) options["uppercase"] = TOOL.check_boolean(kwargs.pop("uppercase", False)) if not hasattr(device, "get_model"): raise RuntimeError( "Device object '{}' do not have 'get_model' method.".format( str(device))) if options["platform"] is None: if str(device.get_model()).upper() in ("LINUX", "CENTOS", "FEDORA"): options["platform"] = "LINUX" else: options["platform"] = "SRX" else: options["platform"] = options["platform"].upper() # interface name maybe set to ge-0/0/1.0 or eth1:1, but only ge-0/0/1 and eth1 needed interface_name = re.split(r"[\.\:]", interface_name)[0] return_value = None if options["platform"] == "LINUX": result = dev.execute_shell_command_on_device( device=device, command="/sbin/ifconfig {}".format(interface_name)) match = re.search(r"ether\s+(\S+)\s+", result) if match and len(re.split(r":", match.group(1))) == 6: return_value = match.group(1) else: raise RuntimeError( "Cannot get interface MAC address from device '{}'\n{}".format( str(device), result)) else: result = dev.execute_cli_command_on_device( device=device, format="xml", channel="xml", xml_to_dict=True, command="show interface {}".format(interface_name)) if "physical-interface" not in result["interface-information"]: msg = "No interface response from device '{}'".format(str(device)) if "rpc-error" in result["interface-information"]: msg = result["interface-information"]["rpc-error"][ "error-message"] raise RuntimeError(msg) return_value = str(result["interface-information"] ["physical-interface"]["hardware-physical-address"]) if options["uppercase"] is True: return_value = return_value.upper() device.log(message="{} return value: {}".format(func_name, return_value), level="INFO") return return_value
def fetch_cpu_pinning_info(self, device_handle, vnf_name): """ Function to fetch the CPU Pinning Information for VNFs hosted on the NFX Python Example: _cpu_pin_ = fetch_cpu_pinning_info(device_handle=_dh_, vnf_name='centos-1') Robot Example: ${cpu_usage} Fetch CPU Pinning Info device_handle=${jdm} vnf_name=centos-1 :params str device_handle: **REQUIRED** Device handle for JDM :params str vnf_name: **REQUIRED** Name of the VNF hosted on the NFX :returns: Dictionary of logical cpu as keys and physical cpus list as value """ try: t.log("INFO", "Fetching CPU Pinning Info of VNF: %s" % vnf_name) _cmd_ = "show system visibility cpu" _output_ = execute_cli_command_on_device(device=device_handle, command=_cmd_) _cpu_pinning_flag_ = False _return_dict_ = {} _found_ = False for _row_ in _output_.split("\n"): _match_ = re.match(r".*CPU\s+Pinning.*", _row_) if _match_ is not None: _cpu_pinning_flag_ = True continue if _cpu_pinning_flag_ is True: _match_ = re.match(r"(\S+)\s+(\d+)\s+(\d+).*", _row_) if _match_ is not None: _vnf_ = _match_.group(1) _vcpu_ = _match_.group(2) _cpu_ = _match_.group(3) t.log( "INFO", "Match: '%s', vnf: '%s', vcpu: '%s', cpu: '%s'" % (_row_, _vnf_, _vcpu_, _cpu_)) if _vnf_ != vnf_name: t.log("INFO", " - vnf ignored") continue if _vcpu_ not in _return_dict_.keys(): _return_dict_[_vcpu_] = [str(_cpu_)] else: _return_dict_[_vcpu_].append(str(_cpu_)) _found_ = True if _found_ is False: raise Exception( "No CPU Pinning Information found for VNF: %s" % vnf_name) else: return True, _return_dict_ except Exception as _exception_: raise Exception("Error: %s: %s" % (type(_exception_), _exception_))
def change_multitenancy_mode(self, device, mode="lsys", **kwargs): """switch logical-system mode to tradition or logical-domain mode. Base on command "set system processes multitenancy mode" to change LSYS mode, and reboot device if needed. This method support both SA/HA. For HA setup, will reboot 2 nodes in parallel and waiting for all FPC online :param STR mode: *OPTIONAL* One of lsys, ld, logical-system or logical-domain (case insensitive). default: lsys :param BOOL reboot_if_need: *OPTIONAL* If multitenancy mode changed and need reboot, reboot device (SA) or all nodes (HA) in parallel. default: True :param INT|STR reboot_timeout: *OPTIONAL* reboot device timeout. default: 600 :param BOOL checking_fpc_online: *OPTIONAL* After rebooting, waiting all FPC PIC online by loop checking. default: True :param INT|STR fpc_online_check_counter: *OPTIONAL* Loop counter to check FPC PIC online. default: 10 :param INT|STR fpc_online_check_interval: *OPTIONAL* Loop interval between each checking. default: 30 :param STR|LIST|TUPLE fpc_online_except_component: *OPTIONAL* As default, all device component must online, but you can give one or more component name here to avoid checking. For example: ``` Slot 0 Online SRX5k SPC II PIC 0 Offline SPU Cp PIC 1 Online SPU Flow PIC 2 Online SPU Flow PIC 3 Offline SPU Flow Slot 2 Online SRX5k IOC II PIC 0 Online 10x 10GE SFP+ ``` Above output will create an internal offline list: ["SLOT 0 PIC 0", "SLOT 0 PIC 3", "PIC 0", "PIC 3"], you can list these keywords in this option to skip them. This means you can just skip "PIC 0" for all SLOT, or set "SLOT 0 PIC 0" for specific PIC. By the way, component keyword is case insensitive, this means keyword "pic 0", "PIC 0", or "Slot 0 Pic 0" all match above output For IOC 3, 2 PICs always offline, and this method will skip them automatically. :param INT|STR timeout: *OPTIONAL* show and commit timeout. default: 300 :return: If lsys mode change succeed and implemented, and all PIC onlined, return True. Otherwise return False """ func_name = self.tool.get_current_function_name() device.log(message=self.tool.print_title(func_name), level="INFO") options = {} options["mode"] = mode.strip().upper() options["reboot_if_need"] = kwargs.get('reboot_if_need', True) options["reboot_timeout"] = int(kwargs.get("reboot_timeout", 600)) options["checking_fpc_online"] = kwargs.get("checking_fpc_online", True) options["fpc_online_check_counter"] = int( kwargs.get("fpc_online_check_counter", 10)) options["fpc_online_check_interval"] = int( kwargs.get("fpc_online_check_interval", 30)) options["fpc_online_except_component"] = kwargs.get( "fpc_online_except_component", ()) options["timeout"] = int( kwargs.get("timeout", self.default["CLI_COMMIT_TIMEOUT"])) if options["mode"] in ("LSYS", "LOGICAL-SYSTEM"): wanted_mode = "logical-system" elif options["mode"] in ("LD", "LOGICAL-DOMAIN"): wanted_mode = "logical-domain" else: raise ValueError( "'mode' must be 'LSYS' 'LD', 'Logical-system' or 'Logical-domain' but got '{}'" .format(options["mode"])) # make sure operate on primary node for HA setup status = device.is_ha() if status is True: if device.node0.is_master() is True: primary_device = device.node0 else: primary_device = device.node1 else: primary_device = device status = dev.execute_config_command_on_device( device=primary_device, command="set system processes multitenancy mode {}".format( wanted_mode), get_response=False, commit=True, timeout=options["timeout"], ) if status is False: device.log( message="commit multitenancy mode configuration failed.", level="ERROR") return status show_cmd = "show system processes multitenancy" response_dict = dev.execute_cli_command_on_device( device=primary_device, command=show_cmd, channel="pyez", format="xml", xml_to_dict=True) device.log(message="show command response:\n{}".format( self.tool.pprint(response_dict)), level="DEBUG") if "multi-routing-engine-results" in response_dict: response_dict = response_dict["multi-routing-engine-results"][ "multi-routing-engine-item"] dev_configure_mode = response_dict["show-mtenancy"][ "mtenancy-mode-config"] dev_configure_status = "" if "mtenancy-mode-config-status" in response_dict["show-mtenancy"]: dev_configure_status = response_dict["show-mtenancy"][ "mtenancy-mode-config-status"] dev_running_mode = response_dict["show-mtenancy"][ "mtenancy-mode-running"] dev_configure_status = "" if "mtenancy-mode-running-status" in response_dict["show-mtenancy"]: dev_configure_status = response_dict["show-mtenancy"][ "mtenancy-mode-running-status"] if dev_configure_mode == dev_running_mode and not re.search( r"must reboot", dev_configure_status): device.log( message= "multitenancy is working on '{}' mode and do not need rebooting." .format(dev_running_mode), level="INFO") device.log(message="{} return value: True".format(func_name), level="INFO") return True dev.reboot_device(device=device, all=True) # waiting for all PIC online return_value = self.chassis.waiting_for_pic_online( device=device, except_component=options["fpc_online_except_component"], check_counter=options["fpc_online_check_counter"], check_interval=options["fpc_online_check_interval"], ) device.log(message="{} return value: {}".format( func_name, return_value), level="INFO") return return_value