def add_del_agent_id(dut, interface_name=None, action="add", cli_type="", sflow_list="global", skip_error_check=False): """ API to add/del SFLOW AGENT ID Author: Chaitanya Vella ([email protected]) :param dut: :param interface_name: :param action: add / del :return: True / False """ cli_type = st.get_ui_type(dut, cli_type=cli_type) cli_type = "klish" if cli_type in ["rest-put", "rest-patch"] else cli_type if action not in ["add", "del"]: st.log("Unsupported action {}..".format(action)) return False if cli_type == "click": if action != "add": command = "config sflow agent-id {}".format(action) else: if not interface_name: st.log("Interface name -- {} not provided ".format( interface_name)) return False command = "config sflow agent-id {} {}".format( action, interface_name) elif cli_type == "klish": if action != "add": command = "no sflow agent-id" else: command = "sflow agent-id {}".format(interface_name) elif cli_type == "rest": url = "{}/SFLOW/SFLOW_LIST={}/agent_id".format(REST_URI, sflow_list) if action == "add": data = {"sonic-sflow:agent_id": interface_name} output = st.rest_modify(dut, url, data) st.log("REST del agent_id OUTPUT -- {}".format(output)) if output and output["status"] != 204: return False else: output = st.rest_delete(dut, url) st.log("REST del agent_id OUTPUT -- {}".format(output)) if output and output["status"] != 204: return False return True else: st.log("UNSUPPORTED CLI TYPE -- {}".format(cli_type)) return False if utils_obj.ensure_cli_type(cli_type, ["click", "klish"]) and command: output = st.config(dut, command, type=cli_type, skip_error_check=skip_error_check) return output return True
def config_max_sessions(dut, **kwargs): """ API to configure max mirror sessions Author: Chaitanya Vella ([email protected]) :param dut: :param kwargs: {"cli_ype":"rest","data":[{"name":"Mirror1","src_ip":"10.20.3.1","dst_ip":"10.23.3.5", "gre_type":"0x855","dscp":16,"ttl":5,"queue":6,"dst_port":"Ethernet28","src_port":"Ethernet20", "direction":"rx/tx"},{"name":"Mirror2","dst_port":"Ethernet20","src_port":"Ethernet22","direction":"rx"}, {"name":"Mirror3","dst_port":"Ethernet26","src_port":"Ethernet22","direction":"tx"}],"action":"config"} :return: response/False """ cli_type = kwargs.get("cli_type", "rest") if cli_type == "rest": status = 204 data = kwargs.get("data") action = data.get("action", "config") rest_url = "/restconf/data/{}".format(YANG_MODEL) if action == "config": if data.get("data"): rest_data = dict() rest_data[YANG_MODEL] = dict() rest_data[YANG_MODEL]["MIRROR_SESSION"] = dict() rest_data[YANG_MODEL]["MIRROR_SESSION"][ "MIRROR_SESSION_LIST"] = make_list(data.get("data")) response = st.rest_modify(dut, rest_url, rest_data) else: st.log("Required data not found -- {}".format(data)) return False elif action == "unconfig": response = st.rest_delete(dut, rest_url) elif action == "get": response = st.rest_read(dut, rest_url) status = 200 else: st.log("Unsupporte ACTION -- {}".format(action)) return False if response and response["status"] == status: return response else: st.log("RESPONSE -- {}".format(response)) return False else: st.log("UNSUPPORTED CLI TYPE -- {}".format(cli_type)) return False
def config_domain(dut, domain_id, **kwargs): ''' Author: [email protected] :param dut: :param domain_id: Mclag domain_id :param local_ip: Mclag peer1 IP :param peer_ip: Mclag peer2 IP :param kwargs: optional parameters can be <local_ip|peer_ip|peer_interface|config|cli_type> :return: usage: config_domain(dut1,10, local_ip="10.10.10.1", peer_ip="10.10.10.2", delay_restore_timer="60") config_domain(dut1,10, local_ip="10.10.10.1", peer_ip="10.10.10.2", peer_interface='Ethernet0001') config_domain(dut1,10, config='del') ''' ### Optional parameters processing local_ip = kwargs.get('local_ip', None) peer_ip = kwargs.get('peer_ip', None) peer_intf = kwargs.get('peer_interface', None) delay_restore_timer = kwargs.get('delay_restore_timer', None) config = kwargs.get('config', 'add') cli_type = kwargs.pop('cli_type', st.get_ui_type(dut, **kwargs)) if cli_type == 'click': cmd = "config mclag {} {}".format(config, domain_id) if config == 'add': if 'local_ip' not in kwargs or 'peer_ip' not in kwargs: st.error("Mandatory parameters local_ip and peer_ip not found") return False cmd += " {} {}".format(local_ip, peer_ip) if 'peer_interface' in kwargs: cmd += ' {}'.format(peer_intf) #cmd += ' \n' output = st.config(dut, cmd) if "Missing argument" in output: st.error("Argument Missing") return False if "invalid peer ip address" in output: st.error("Invalid peer_ip address") return False if "invalid local ip address" in output: st.error("Invalid local_ip address") return False if "interface name is invalid" in output: st.error("Invalid peer interface") return False elif cli_type == 'klish': config = 'no ' if config == 'del' else '' if config == '': cmd = "mclag domain {}".format(domain_id) if 'local_ip' in kwargs: cmd = cmd + "\n" + "source-ip {}".format(local_ip) if 'peer_ip' in kwargs: cmd = cmd + "\n" + "peer-ip {}".format(peer_ip) if 'peer_interface' in kwargs: pintf = get_interface_number_from_name(peer_intf) cmd = cmd + "\n" + "peer-link {} {}".format( pintf['type'], pintf['number']) if 'delay_restore_timer' in kwargs: cmd = cmd + "\n" + "delay-restore {}".format( delay_restore_timer) cmd = cmd + "\n" + "exit" elif config == 'no ': if 'local_ip' in kwargs or 'peer_ip' in kwargs or 'peer_interface' in kwargs or 'delay_restore_timer' in kwargs: cmd = "mclag domain {}".format(domain_id) if 'local_ip' in kwargs: cmd = cmd + "\n" + "{}source-ip".format(config) if 'peer_ip' in kwargs: cmd = cmd + "\n" + "{}peer-ip".format(config) if 'peer_interface' in kwargs: cmd = cmd + "\n" + "{}peer-link".format(config) if 'delay_restore_timer' in kwargs: cmd = cmd + "\n" + "{}delay-restore".format(config) cmd = cmd + "\n" + "exit" else: cmd = "{}mclag domain {}".format(config, domain_id) output = st.config(dut, cmd, type="klish", conf=True) if "Could not connect to Management REST Server" in output: st.error("klish mode not working.") return False elif cli_type in ["rest-put", "rest-patch"]: if config == 'del': rest_urls = st.get_datastore(dut, 'rest_urls') rest_url_del = rest_urls['mclag_config_domain'].format( int(domain_id)) output = st.rest_delete(dut, rest_url_del) if not output["status"] in [200, 204]: st.error( "Failed to delete the mclag domain using REST in {} due to bad request {}" .format(dut, output["status"])) return False else: st.log( "PASS: Rest delete mclag domain return status {}".format( output['status'])) return True if 'local_ip' in kwargs: rest_urls = st.get_datastore(dut, 'rest_urls') rest_url = rest_urls['mclag_config_all'] rest_data = { "openconfig-mclag:mclag-domains": { "mclag-domain": [{ "domain-id": int(domain_id), "config": { "domain-id": int(domain_id), "source-address": local_ip } }] } } output = st.rest_create(dut, path=rest_url, data=rest_data) if output["status"] not in [200, 204, 201]: st.error( "Failed to configure using POST source-address in {} due to bad request {} seen for REST command" .format(dut, output["status"])) return False else: st.log( "PASS: Rest operation using POST for source-address return status {}" .format(output['status'])) if 'peer_ip' in kwargs: rest_urls = st.get_datastore(dut, 'rest_urls') rest_url = rest_urls['mclag_config_peer_ip'].format(int(domain_id)) rest_data = {"openconfig-mclag:peer-address": peer_ip} output = st.rest_modify(dut, path=rest_url, data=rest_data) if output["status"] not in [200, 204, 201]: st.error( "Failed to configure peer-address in {} due to bad request {} seen for REST command" .format(dut, output["status"])) return False else: st.log( "PASS: Rest operation for peer-address return status {}". format(output['status'])) if 'peer_interface' in kwargs: rest_urls = st.get_datastore(dut, 'rest_urls') rest_url = rest_urls['mclag_config_peer_link'].format( int(domain_id)) rest_data = {"openconfig-mclag:peer-link": peer_intf} output = st.rest_modify(dut, path=rest_url, data=rest_data) if output["status"] not in [200, 204, 201]: st.error( "Failed to configure peer-link in {} due to bad request {} seen for REST command" .format(dut, output["status"])) return False else: st.log("PASS: Rest operation for peer-link return status {}". format(output['status'])) if 'delay_restore_timer' in kwargs: rest_urls = st.get_datastore(dut, 'rest_urls') rest_url = rest_urls['mclag_config_delay_restore'].format( int(domain_id)) rest_data = { "openconfig-mclag:delay-restore": int(delay_restore_timer) } output = st.rest_modify(dut, path=rest_url, data=rest_data) if output["status"] not in [200, 204, 201]: st.error( "Failed to configure delay_restore_timer in {} due to bad request {} seen for REST command" .format(dut, output["status"])) return False else: st.log( "PASS: Rest operation for delay_restore_timer return status {}" .format(output['status'])) if 'keepalive_interval' in kwargs: rest_urls = st.get_datastore(dut, 'rest_urls') rest_url = rest_urls['mclag_config_keepalive'].format( int(domain_id)) rest_data = { "openconfig-mclag:keepalive-interval": int(kwargs['keepalive_interval']) } output = st.rest_modify(dut, path=rest_url, data=rest_data) if output["status"] not in [200, 204, 201]: st.error( "Failed to configure keepalive-interval in {} due to bad request {} seen for REST command" .format(dut, output["status"])) return False else: st.log( "PASS: Rest operation for keepalive-interval return status {}" .format(output['status'])) if 'session_timeout' in kwargs: rest_url = rest_urls['mclag_config_session_timeout'].format( int(domain_id)) rest_data = { "openconfig-mclag:session-timeout": int(kwargs['session_timeout']) } output = st.rest_modify(dut, path=rest_url, data=rest_data) if output["status"] not in [200, 204, 201]: st.error( "Failed to configure session-timeout in {} due to bad request {} seen for REST command" .format(dut, output["status"])) return False else: st.log( "PASS: Rest operation for session-timeout return status {}" .format(output['status'])) if 'mclag_system_mac' in kwargs: rest_url = rest_urls['mclag_config_mclag_system_mac'].format( int(domain_id)) rest_data = { "openconfig-mclag:mclag-system-mac": kwargs['mclag_system_mac'] } output = st.rest_modify(dut, path=rest_url, data=rest_data) if output["status"] not in [200, 204, 201]: st.error( "Failed to configure mclag-system-mac in {} due to bad request {} seen for REST command" .format(dut, output["status"])) return False else: st.log( "PASS: Rest operation for mclag-system-mac return status {}" .format(output['status'])) for arg1 in kwargs: if arg1 not in [ 'mclag_system_mac', 'session_timeout', 'keepalive_interval', 'delay_restore_timer', 'peer_interface', 'peer_ip', 'local_ip' ]: st.error("ARG {} is not supported through REST".format(arg1)) return True
def config_attributes(dut, **kwargs): """ Common API to configure sflow sample rate on interface, polling interval and sample rate per speed. Author: Chaitanya Vella ([email protected]) :param dut: :param kwargs: :return: True NOTE: 1) To configure interface sample rate, config_sflow_attributes(dut, sample_rate=100, interface_name="Ethernet10") 2) To configure polling interval config_sflow_attributes(dut, polling_interval=20) 3) To configure sample rate per speed config_sflow_attributes(dut, speed=10G, sample_rate=10000) """ cli_type = st.get_ui_type(dut, **kwargs) cli_type = "klish" if cli_type in ["rest-put", "rest-patch"] else cli_type sflow_key = kwargs.get("sflow_key", "global") command = "" commands = list() if "sample_rate" in kwargs and "interface_name" in kwargs: if cli_type == "click": command += "config sflow interface sample-rate {} {}".format( kwargs["interface_name"], kwargs["sample_rate"]) commands.append(command) elif cli_type == "klish": interface_details = utils_obj.get_interface_number_from_name( kwargs["interface_name"]) if not interface_details: st.log( "Interface details not found {}".format(interface_details)) return False commands.append("interface {} {}".format( interface_details.get("type"), interface_details.get("number"))) if "no_form" in kwargs: command = "no sflow sampling-rate" else: command = "sflow sampling-rate {}".format( kwargs["sample_rate"]) commands.append(command) commands.append("exit") elif cli_type == "rest": data = {"sonic-sflow:sample_rate": int(kwargs["sample_rate"])} url = "{}/SFLOW_SESSION/SFLOW_SESSION_LIST={}/sample_rate".format( REST_URI, kwargs["interface_name"]) output = st.rest_modify(dut, url, data) st.log("REST config_attributes SAMPLE RATE OUTPUT -- {}".format( output)) if output and output["status"] != 204: return False return True else: st.log("UNSUPPORTED CLI TYPE -- {}".format(cli_type)) return False st.config(dut, commands, type=cli_type) if "polling_interval" in kwargs: if cli_type == "click": command += "config sflow polling-interval {};".format( kwargs["polling_interval"]) commands.append(command) elif cli_type == "klish": if "no_form" in kwargs: command = "no sflow polling-interval" else: command = "sflow polling-interval {}".format( kwargs["polling_interval"]) commands.append(command) elif cli_type == "rest": data = { "sonic-sflow:polling_interval": int(kwargs["polling_interval"]) } url = "{}/SFLOW/SFLOW_LIST={}/polling_interval".format( REST_URI, sflow_key) output = st.rest_modify(dut, url, data) st.log("REST config_attributes POLLING RATE OUTPUT -- {}".format( output)) if output and output["status"] != 204: return False return True else: st.log("UNSUPPORTED CLI TYPE -- {}".format(cli_type)) return False st.config(dut, commands, type=cli_type) return True
def enable_disable_config(dut, interface=False, interface_name=None, action="enable", cli_type="", sflow_key="global"): """ API to enable / disable SFLOW Globally / on interface level Author: Chaitanya Vella ([email protected]) :param dut: :param interface: :param interface_name: :param action: :return: """ cli_type = st.get_ui_type(dut, cli_type=cli_type) cli_type = "klish" if cli_type in ["rest-put", "rest-patch"] else cli_type if action not in ["enable", "disable"]: st.log("Unsupported action {} ".format(action)) return False if interface and interface_name: commands = list() if cli_type == "click": command = "config sflow interface {} {}".format( action, interface_name) commands.append(command) elif cli_type == "klish": interface_details = utils_obj.get_interface_number_from_name( interface_name) if not interface_details: st.log( "Interface details not found {}".format(interface_details)) return False commands.append("interface {} {}".format( interface_details.get("type"), interface_details.get("number"))) if action == "enable": command = "sflow {}".format(action) else: command = "no sflow enable" commands.append(command) elif cli_type == "rest": session_list = dict() session_list["sonic-sflow:SFLOW_SESSION_LIST"] = list() session_data = dict() session_data["ifname"] = interface_name session_data[ "admin_state"] = "up" if action == "enable" else "down" session_list["sonic-sflow:SFLOW_SESSION_LIST"].append(session_data) url = "{}/SFLOW_SESSION".format(REST_URI) output = st.rest_modify(dut, url, session_list, SFLOW_SESSION_LIST=interface_name) st.log("ENABLE / DISABLE SFLOW AT INTF level -- {}".format(output)) if output and output["status"] != 204: return False return True else: st.log("UNSUPPORTED CLI TYPE -- {}".format(cli_type)) return False if commands: st.config(dut, commands, type=cli_type) else: if cli_type == "click": command = "config sflow {}".format(action) elif cli_type == "klish": if action != "enable": command = "no sflow enable" else: command = "sflow enable" elif cli_type == "rest": data = { "sonic-sflow:admin_state": "up" if action == "enable" else "down" } url = "{}/SFLOW/SFLOW_LIST={}/admin_state".format( REST_URI, sflow_key) output = st.rest_modify(dut, url, data) st.log( "ENABLE / DISABLE SFLOW AT GLOBAL level -- {}".format(output)) if output and output["status"] != 204: return False return True else: st.log("UNSUPPORTED CLI TYPE -- {}".format(cli_type)) return False if command: st.config(dut, command, type=cli_type) return True
def add_del_collector(dut, collector_name, ip_address=None, port_number=None, action="add", cli_type="", skip_error_check=False): """ API to add/del SFLOW collector Author: Chaitanya Vella ([email protected]) :param dut: :param collector_name: :param ip_address: IPV4 / IPV6 address, this is optional for del operations :param port_number: None, this is optional for del operations :param action: add / del :return: True / False """ cli_type = st.get_ui_type(dut, cli_type=cli_type) cli_type = "klish" if cli_type in ["rest-put", "rest-patch"] else cli_type command = None if action == "add": if ip_address: if cli_type == "click": command = "config sflow collector add {} {} --port {}".format(collector_name, ip_address, port_number) if port_number else \ "config sflow collector add {} {}".format(collector_name, ip_address) elif cli_type == "klish": command = "sflow collector {} {}".format( ip_address, port_number) if port_number else \ "sflow collector {}".format(ip_address) elif cli_type == "rest": data = dict() data["sonic-sflow:SFLOW_COLLECTOR"] = dict() data["sonic-sflow:SFLOW_COLLECTOR"][ "sonic-sflow:SFLOW_COLLECTOR_LIST"] = list() collector_data = dict() collector_data["collector_name"] = collector_name collector_data["collector_ip"] = ip_address collector_data["collector_port"] = int( port_number) if port_number else DEFAULT_COLLECTOR_PORT data["sonic-sflow:SFLOW_COLLECTOR"][ "sonic-sflow:SFLOW_COLLECTOR_LIST"].append(collector_data) json_data = data url = "{}/SFLOW_COLLECTOR".format(REST_URI) output = st.rest_modify(dut, url, json_data) st.log( "ADD / DEL COLLECTOR AT INTF level -- {}".format(output)) if output and output["status"] != 204: return False return True else: st.log("UNSUPPORTED CLI TYPE -- {}".format(cli_type)) return False else: st.log("IP ADDRESS not provided for add operation ..") return False elif action == "del": if cli_type == "click": command = "config sflow collector del {}".format(collector_name) elif cli_type == "klish": command = "no sflow collector {} {}".format( ip_address, port_number) if port_number else \ "no sflow collector {}".format(ip_address) elif cli_type == "rest": url = "{}/SFLOW_COLLECTOR".format(REST_URI) output = st.rest_delete(dut, url, SFLOW_COLLECTOR_LIST=collector_name) st.log("ADD / DEL COLLECTOR AT INTF level -- {}".format(output)) if output and output["status"] != 204: return False return True else: st.log("UNSUPPORTED CLI TYPE -- {}".format(cli_type)) return False if cli_type != "rest" and command and utils_obj.ensure_cli_type( cli_type, ["click", "klish"]): output = st.config(dut, command, type=cli_type, skip_error_check=skip_error_check) return output return True
def rest_operation(dut, **kwargs): op = kwargs.get("http_method") url = kwargs.get("rest_url") data = kwargs.get("json_data") timeout = kwargs.get("timeout", 5) log_msg = [] status_map = {200 : "Rest operation successful", 201 : "Rest operation successful", 204 : "Rest operation successful", 400 : "Bad Request", 401 : "Unauthorized", 403 : "Forbidden", 404 : "Page not found", 405 : "Method not allowed", 409 : "Conflict", 415 : "Unsupported Media Type", 500 : "Internal Server Error"} retval = {} rest_result = True log_msg.append("[{}] -- HTTP METHOD : {}".format(dut, op.upper())) log_msg.append("URL : {}".format(url)) if data: log_msg.append("PAYLOAD : {}".format(data)) if not op or not url: st.log("Please provide http_method: {} or rest_url: {}".format(op,url)) return False op = op.lower() if op in ["get","delete"]: params = {"path":url, "rest_timeout":timeout} elif op in ["post", "put", "patch"]: params = {"path": url, "data":data,"rest_timeout": timeout} else: st.log("Please provide valid Http method") return False if kwargs.get("username"): params.update({"rest_username":kwargs.get("username")}) if kwargs.get("password"): params.update({"rest_password":kwargs.get("password")}) for iteration in range(1,5): try: if op == "get": retval = st.rest_read(dut, **params) elif op == "post": retval = st.rest_create(dut, **params) elif op == "put": retval = st.rest_update(dut, **params) elif op == "delete": retval = st.rest_delete(dut, **params) elif op == "patch": retval = st.rest_modify(dut, **params) else: st.log("Please provide valid Http method") return False break except Exception as e: if iteration > 2: credentials = st.get_credentials(dut) st.rest_init(dut, credentials[0], credentials[1], credentials[2]) if op == "get": tout = 180 if int(timeout) < 180 else timeout st.log("Setting timeout to {} sec".format(tout)) params.update({"rest_timeout": tout}) st.error(e) if "url" in retval.keys(): host_ip = re.findall(r'([0-9]+(?:\.[0-9]+){3})', retval["url"]) if host_ip: log_msg.insert(1, "HOST IP : {}".format(host_ip[0])) if "status" in retval.keys(): log_msg.append("STATUS : {} - {}".format(retval["status"], status_map[retval["status"]])) rest_result = True if retval["status"] in [200, 201, 204] else False if op == "get": if "output" in retval.keys(): log_msg.append("OUTPUT : {}".format(retval["output"])) if rest_result: st.log("{}".format(", ".join(log_msg))) else: st.error("{}".format(", ".join(log_msg))) return retval