def add_l2_port(port_name, port_desc=None, port_admin_state="up", **kwargs): """ Perform a POST call to create a Port table entry for physical L2 interface. If the Port table entry exists, this function will perform a PUT call to update the entry with the given parameters. :param port_name: Alphanumeric Port name :param port_desc: Optional description for the interface. Defaults to nothing if not specified. :param port_admin_state: Optional administratively-configured state of the port. Defaults to "up" if not specified :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ ports_list = get_all_ports(**kwargs) port_name_percents = common_ops._replace_special_characters(port_name) port_data = { "admin": port_admin_state, "interfaces": ["/rest/v1/system/interfaces/%s" % port_name_percents], "name": port_name, "routing": False } if port_desc is not None: port_data['description'] = port_desc if "/rest/v1/system/ports/%s" % port_name_percents not in ports_list: target_url = kwargs["url"] + "system/ports" payload_data = json.dumps(port_data, sort_keys=True, indent=4) response = kwargs["s"].post(target_url, data=payload_data, verify=False) if not common_ops._response_ok(response, "POST"): print( "FAIL: Adding Port table entry '%s' failed with status code %d" % (port_name, response.status_code)) else: print("SUCCESS: Adding Port table entry '%s' succeeded" % port_name) else: target_url = kwargs["url"] + "system/ports/%s" % port_name_percents port_data.pop( 'name', None ) # must remove this item from the json since name can't be modified payload_data = json.dumps(port_data, sort_keys=True, indent=4) response = kwargs["s"].put(target_url, data=payload_data, verify=False) if not common_ops._response_ok(response, "PUT"): print( "FAIL: Updating Port table entry '%s' failed with status code %d" % (port_name, response.status_code)) else: print("SUCCESS: Updating Port table entry '%s' succeeded" % port_name)
def _update_port_loop_protect(interface_name, action="", vlan_list=[], **kwargs): """ Perform GET and PUT calls to apply Loop-protect options on an interface. Note that Loop-protect requires that the interface is L2, so this function will also update the interface to reflect that. :param interface_name: Alphanumeric String that is the name of the interface that will apply loop-protect options :param action: Alphanumeric String that will specify the actions for the Loop-protect interface. The options are "do-not-disable", "tx-disable", "tx-rx-disable", or None. :param vlan_list: List of VLANs that will be configured for Loop-protect on the interface :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ int_name_percents = common_ops._replace_special_characters(interface_name) int_data = interface.get_interface(int_name_percents, depth=1, selector="writable", **kwargs) if interface_name.startswith('lag'): if int_data['interfaces']: int_data['interfaces'] = common_ops._dictionary_to_list_values(int_data['interfaces']) if int_data['vlan_trunks']: int_data['vlan_trunks'] = common_ops._dictionary_to_list_values(int_data['vlan_trunks']) if int_data['loop_protect_vlan']: int_data['loop_protect_vlan'] = common_ops._dictionary_to_list_values(int_data['loop_protect_vlan']) int_data['loop_protect_enable'] = True # make interface L2 int_data['routing'] = False # strings appended to output prints for status action_output = "" vlan_output = "" if action not in ['do-not-disable', 'tx-disable', 'tx-rx-disable', None]: raise Exception("ERROR: Action should be 'do-not-disable', 'tx-disable', 'tx-rx-disable' or None") elif action: int_data['loop_protect_action'] = action action_output = " with Action %s " % action if vlan_list: vlan_output = " with VLAN(s) [" for vlan in vlan_list: vlan_url = "/rest/v10.04/system/vlans/%s" % vlan if vlan_url not in int_data['loop_protect_vlan']: int_data['loop_protect_vlan'].append(vlan_url) vlan_output += (str(vlan) + " ") vlan_output += "] " target_url = kwargs["url"] + "system/interfaces/%s" % int_name_percents put_data = json.dumps(int_data, sort_keys=True, indent=4) response = kwargs["s"].put(target_url, data=put_data, verify=False) if not common_ops._response_ok(response, "PUT"): print("FAIL: Applying Loop-protect to Interface '%s'%s%s failed with status code %d" % (interface_name, action_output, vlan_output, response.status_code)) else: print("SUCCESS: Applying Loop-protect to Interface '%s'%s%s succeeded" % (interface_name, action_output, vlan_output))
def _clear_port_loop_protect_v1(port_name, **kwargs): """ Perform GET and PUT calls to clear a Port's Loop-protect settings :param port_name: Alphanumeric name of the Port :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ port_name_percents = common_ops._replace_special_characters(port_name) port_data = port.get_port(port_name, depth=0, selector="configuration", **kwargs) port_data.pop('loop_protect_enable', None) port_data.pop('loop_protect_action', None) port_data['loop_protect_vlan'] = [] # must remove these fields from the data since they can't be modified port_data.pop('name', None) port_data.pop('origin', None) target_url = kwargs["url"] + "system/ports/%s" % port_name_percents put_data = json.dumps(port_data, sort_keys=True, indent=4) response = kwargs["s"].put(target_url, data=put_data, verify=False) if not common_ops._response_ok(response, "PUT"): print("FAIL: Clearing Loop-protect options on Port '%s' failed with status code %d" % (port_name, response.status_code)) else: print("SUCCESS: Clearing the Loop-protect options on Port '%s' succeeded" % (port_name))
def _get_dhcp_relay(vrf_name, port_name, **kwargs): """ Perform a GET call to get DHCP data for an interface :param vrf_name: Alphanumeric name of VRF :param port_name: L3 interface's Port table entry name :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Dictionary containing DHCP Relay data for interface """ payload = {"selector": "writable"} target_url = kwargs["url"] + "system/dhcp_relays/%s,%s" % (vrf_name, port_name) response = kwargs["s"].get(target_url, verify=False, params=payload, timeout=2) if not common_ops._response_ok(response, "GET"): print( "FAIL: Getting IPv4 DHCP helper(s) for Port '%s' failed with status code %d" % (port_name, response.status_code)) else: print("SUCCESS: Getting IPv4 DHCP helper(s) for Port '%s' succeeded" % port_name) return response.json()
def _delete_dhcp_relays(port_name, vrf_name="default", **kwargs): """ Perform a DELETE call to delete all the IPv4 DHCP helper(s) for an L3 interface. :param port_name: Alphanumeric name of the Port :param vrf_name: Alphanumeric name of the VRF :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ dhcp_helpers_dict = get_all_dhcp_relays(**kwargs) if "%s,%s" % (vrf_name, port_name) in dhcp_helpers_dict: target_url = kwargs["url"] + "system/dhcp_relays/%s,%s" % (vrf_name, port_name) response = kwargs["s"].delete(target_url, verify=False) if not common_ops._response_ok(response, "DELETE"): print( "FAIL: Deleting all DHCP relays from interface Port '%s' failed with status code %d" % (port_name, response.status_code)) else: print( "SUCCESS: Deleting all DHCP relays from interface Port '%s' succeeded" % port_name) else: print( "SUCCESS: No need to delete DHCP relays from SVI Port '%s' since they don't exist" % port_name)
def get_mac_info(vlan_id, mac_type, mac_addr, **kwargs): """ Perform a GET call to get MAC info :param vlan_id: Numeric ID of VLAN :param mac_type: The source of the MAC address. Must be "dynamic," "VSX," "static," "VRRP," "port-access-security," "evpn," or "hsc" :param mac_addr: MAC address :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Dictionary containing MAC data """ target_url = kwargs["url"] + "system/vlans/%d/macs/%s/%s" % ( vlan_id, mac_type, mac_addr) response = kwargs["s"].get(target_url, verify=False) if not common_ops._response_ok(response, "GET"): print( "FAIL: Getting data for MAC '%s' of VLAN ID '%d' failed with status code %d" % (mac_addr, vlan_id, response.status_code)) else: print("SUCCESS: Getting data for MAC '%s' of VLAN ID '%d' succeeded" % (mac_addr, vlan_id)) mac_data = response.json() return mac_data
def _clear_port_acl_in(port_name, list_type, **kwargs): """ Perform GET and PUT calls to clear a Port's Ingress ACL :param port_name: Alphanumeric name of the Port :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ port_name_percents = common_ops._replace_special_characters(port_name) port_data = interface.get_interface(port_name, depth=1, selector="writable", **kwargs) if list_type is "ipv6": port_data.pop('aclv6_in_cfg', None) port_data.pop('aclv6_in_cfg_version', None) elif list_type is "ipv4": port_data.pop('aclv4_in_cfg', None) port_data.pop('aclv4_in_cfg_version', None) target_url = kwargs["url"] + "system/interface/%s" % port_name_percents put_data = json.dumps(port_data, sort_keys=True, indent=4) response = kwargs["s"].put(target_url, data=put_data, verify=False) if not common_ops._response_ok(response, "PUT"): print( "FAIL: Clearing %s Ingress ACL on Port '%s' failed with status code %d" % (list_type, port_name, response.status_code)) else: print("SUCCESS: Clearing %s Ingress ACL on Port '%s' succeeded" % (list_type, port_name))
def delete_acl_entry(list_name, list_type, sequence_num, **kwargs): """ Perform a DELETE call to delete an ACL entry :param list_name: Alphanumeric name of the ACL :param list_type: Type should be one of "ipv4," "ipv6," or "mac" :param sequence_num: Integer ID for the entry. :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ acl_entries_dict = get_all_acl_entries(list_name, list_type, **kwargs) if "/rest/v1/system/acls/%s/%s/cfg_aces/%d" % ( list_name, list_type, sequence_num) in acl_entries_dict.values(): target_url = kwargs["url"] + "system/acls/%s/%s/cfg_aces/%d" % ( list_name, list_type, sequence_num) response = kwargs["s"].delete(target_url, verify=False) if not common_ops._response_ok(response, "DELETE"): print( "FAIL: Deleting entry %d in %s ACL '%s' failed with status code %d" % (sequence_num, list_type, list_name, response.status_code)) else: print("SUCCESS: Deleting entry %d in %s ACL '%s' succeeded" % (sequence_num, list_type, list_name)) else: print( "SUCCESS: No need to delete entry %d in %s ACL '%s' since it doesn't exist" % (sequence_num, list_type, list_name))
def _update_acl(list_name, list_type, **kwargs): """ Perform a PUT call to version-up an ACL. This is required whenever entries of an ACL are changed in any way. :param list_name: Alphanumeric name of the ACL :param list_type: Type should be one of "ipv4," "ipv6," or "mac" :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ acl_data = get_acl(list_name, list_type, **kwargs) acl_key = "{},{}".format(list_name, list_type) acl_data['cfg_version'] = random.randint(-9007199254740991, 9007199254740991) target_url = kwargs["url"] + "system/acls/%s" % acl_key put_data = json.dumps(acl_data, sort_keys=True, indent=4) response = kwargs["s"].put(target_url, data=put_data, verify=False) if not common_ops._response_ok(response, "PUT"): print("FAIL: Updating %s ACL '%s' failed with status code %d" % (list_type, list_name, response.status_code)) else: print("SUCCESS: Updating %s ACL '%s' succeeded" % (list_type, list_name))
def _add_vni_mapping(vni, vxlan, vlan, **kwargs): """ Perform POST call to create a Virtual Network ID and Map it to VLANs for a supplied VXLAN :param vni: Integer representing the Virtual Network ID :param vxlan: Alphanumeric of the VXLAN that the VNI will be associated with :param vlan: VLAN that the VNI will be mapped to :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ vni_list = get_vni_list(**kwargs) if "vxlan_vni,%d" % vni not in vni_list: vni_data = { "id": vni, "interface": "/rest/v10.04/system/interfaces/%s" % vxlan, "type": "vxlan_vni", "vlan": "/rest/v10.04/system/vlans/%d" % vlan } target_url = kwargs["url"] + "system/virtual_network_ids" post_data = json.dumps(vni_data, sort_keys=True, indent=4) response = kwargs["s"].post(target_url, data=post_data, verify=False, timeout=2) if not common_ops._response_ok(response, "POST"): print("FAIL: Creating VNI '%s' for VXLAN '%s' failed with status code %d" % (vni, vxlan, response.status_code)) else: print("SUCCESS: Creating VNI '%s' for VXLAN '%s' succeeded" % (vni, vxlan)) else: print("SUCCESS: No need to create VNI '%s' for VXLAN '%s' as it already exists" % (vni, vxlan))
def create_evpn_instance(**kwargs): """ Perform POST calls to create an EVPN instance :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ current_evpn = get_evpn_info(**kwargs) if current_evpn: print( "SUCCESS: No need to create EVPN instance since it already exists") else: evpn_data = {} target_url = kwargs["url"] + "system/evpns" post_data = json.dumps(evpn_data, sort_keys=True, indent=4) response = kwargs["s"].post(target_url, data=post_data, verify=False, timeout=2) if not common_ops._response_ok(response, "POST"): print("FAIL: Creating EVPN Instance failed with status code %d" % response.status_code) else: print("SUCCESS: Creating EVPN Instance succeeded")
def _get_all_acl_entries(list_name, list_type, **kwargs): """ Perform a GET call to get all entries of an ACL :param list_name: Alphanumeric name of the ACL :param list_type: Type should be one of "ipv4," "ipv6," or "mac" :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Dictionary containing queue profile entry URIs """ target_url = kwargs["url"] + "system/acls/%s,%s?attributes=cfg_aces" % ( list_name, list_type) response = kwargs["s"].get(target_url, verify=False) if not common_ops._response_ok(response, "GET"): print( "FAIL: Getting dictionary of URIS of entries in %s ACL '%s' failed with status code %d" % (list_type, list_name, response.status_code)) else: print( "SUCCESS: Getting dictionary of URIs of entries in %s ACL '%s' succeeded" % (list_type, list_name)) acl_entries = response.json() # for some reason, this API returns a list when empty, and a dictionary when there is data # make this function always return a dictionary, if not acl_entries: return {} else: return acl_entries
def _delete_ipv6_address(port_name, ip, **kwargs): """ Perform a DELETE call to remove an IPv6 address from an Interface. :param port_name: Alphanumeric Interface name :param ip: IPv6 address assigned to the interface that will be removed. :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ if ip in interface.get_ipv6_addresses(port_name, **kwargs): port_name_percents = common_ops._replace_special_characters(port_name) ip_address = common_ops._replace_special_characters(ip) target_url = kwargs["url"] + "system/interfaces/%s/ip6_addresses/%s" % ( port_name_percents, ip_address) response = kwargs["s"].delete(target_url, verify=False) if not common_ops._response_ok(response, "DELETE"): print( "FAIL: Deleting IPv6 Address '%s' from Port table entry '%s' failed with status code %d" % (ip, port_name, response.status_code)) else: print( "SUCCESS: Deleting IPv6 Address '%s' from Port table entry '%s' succeeded" % (ip, port_name)) else: print( "SUCCESS: No need to delete IPv6 Address '%s' from Port table entry '%s' since it does not exist" % (ip, port_name))
def login(base_url, username=None, password=None): """ Perform a POST call to login and gain access to other API calls. If either username or password is not specified, user will be prompted to enter the missing credential(s). :param base_url: URL in main() function :param username: username :param password: password :return: requests.session object with loaded cookie jar """ if username is None and password is None: username = input('Enter username: '******'ERROR: Error connecting to host: connection attempt timed out.') exit(-1) # Response OK check needs to be passed "PUT" since this POST call returns 200 instead of conventional 201 if not common_ops._response_ok(response, "PUT"): print("FAIL: Login failed with status code %d" % response.status_code) exit(-1) else: print("SUCCESS: Login succeeded") return s
def delete_vrf(vrf_name, **kwargs): """ Perform a DELETE call to delete a VRF. Note that this functions has logic that works for both v1 and v10.04 :param vrf_name: Alphanumeric name of VRF :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ vrf_list = get_all_vrfs(**kwargs) if kwargs["url"].endswith("/v1/"): vrf_check = "/rest/v1/system/vrfs/%s" % vrf_name else: # Else logic designed for v10.04 and later vrf_check = vrf_name if vrf_check in vrf_list: target_url = kwargs["url"] + "system/vrfs/%s" % vrf_name response = kwargs["s"].delete(target_url, verify=False) if not common_ops._response_ok(response, "DELETE"): print("FAIL: Deleting VRF '%s' failed with status code %d" % (vrf_name, response.status_code)) else: print("SUCCESS: Deleting VRF '%s' succeeded" % vrf_name) else: print("SUCCESS: No need to delete VRF '%s' since it doesn't exist" % vrf_name)
def _get_vlan(vlan_id, depth=1, selector="writable", **kwargs): """ Perform a GET call to retrieve data for a VLAN table entry :param depth: Integer deciding how many levels into the API JSON that references will be returned. :param selector: Alphanumeric option to select specific information to return. The options are 'configuration', 'status', or 'statistics'. If running v10.04 or later, an additional option 'writable' is included. :param vlan_id: Numeric ID of VLAN :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Dictionary containing port data """ if selector not in [ 'configuration', 'status', 'statistics', 'writable', None ]: raise Exception( "ERROR: Selector should be 'configuration', 'status', 'statistics', or 'writable'" ) target_url = kwargs["url"] + "system/vlans/%d" % vlan_id payload = {"depth": depth, "selector": selector} response = kwargs["s"].get(target_url, verify=False, params=payload, timeout=2) if not common_ops._response_ok(response, "GET"): print( "FAIL: Getting VLAN ID '%d' table entry failed with status code %d" % (vlan_id, response.status_code)) output = {} else: print("SUCCESS: Getting VLAN ID '%d' table entry succeeded" % vlan_id) output = response.json() return output
def _get_vrf(vrf_name, depth=1, selector=None, **kwargs): """ Perform a GET call to get data for a VRF table entry :param vrf_name: Alphanumeric name of the VRF :param depth: Integer deciding how many levels into the API JSON that references will be returned. :param selector: Alphanumeric option to select specific information to return. The options are 'configuration', 'status', 'statistics' or 'writable'. :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Dictionary containing the VRF data """ if selector not in ['configuration', 'status', 'statistics', 'writable', None]: raise Exception("ERROR: Selector should be 'configuration', 'status', 'statistics', or 'writable'") target_url = kwargs["url"] + "system/vrfs/%s" % vrf_name payload = { "depth": depth, "selector": selector } response = kwargs["s"].get(target_url, verify=False, params=payload, timeout=2) if not common_ops._response_ok(response, "GET"): print("FAIL: Getting VRF table entry '%s' failed with status code %d" % (vrf_name, response.status_code)) vrf = [] else: print("SUCCESS: Getting VRF table entry '%s' succeeded" % vrf_name) vrf = response.json() return vrf
def _delete_vlan(vlan_id, **kwargs): """ Perform a DELETE call to delete VLAN. :param vlan_id: Numeric ID of VLAN :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ vlans_dict = get_all_vlans(**kwargs) if str(vlan_id) in vlans_dict: target_url = kwargs["url"] + "system/vlans/%s" % vlan_id response = kwargs["s"].delete(target_url, verify=False) if not common_ops._response_ok(response, "DELETE"): print("FAIL: Deleting VLAN ID: '%s' failed with status code %d" % (vlan_id, response.status_code)) else: print("SUCCESS: Deleting VLAN ID: '%s' succeeded" % vlan_id) else: print( "SUCCESS: No need to remove VLAN ID '%d' since it doesn't exist" % vlan_id)
def _get_acl(list_name, list_type, **kwargs): """ Perform a GET call to get details of a particular ACL :param list_name: Alphanumeric name of the ACL :param list_type: Type should be one of "ipv4," "ipv6," or "mac" :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Dictionary containing data about a particular ACL """ acl_key = "{},{}".format(list_name, list_type) target_url = kwargs[ "url"] + "system/acls/%s?depth=2&selector=writable" % acl_key response = kwargs["s"].get(target_url, verify=False) if not common_ops._response_ok(response, "GET"): print("FAIL: Getting %s ACL '%s' failed with status code %d" % (list_type, list_name, response.status_code)) else: print("SUCCESS: Getting %s ACL '%s' succeeded" % (list_type, list_name)) acl = response.json() return acl
def _get_vsx_v1(depth, selector, **kwargs): """ Perform a GET call to get get the current VSX information on a system. :param depth: Integer deciding how many levels into the API JSON that references will be returned. :param selector: Alphanumeric option to select specific information to return. The options are 'configuration', 'status', or 'statistics'. :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: JSON of VSX information """ if selector not in ['configuration', 'status', 'statistics', None]: raise Exception( "ERROR: Selector should be 'configuration', 'status', or 'statistics'" ) target_url = kwargs["url"] + "system/vsx" payload = {"depth": depth, "selector": selector} response = kwargs["s"].get(target_url, verify=False, params=payload, timeout=2) result = [] if not common_ops._response_ok(response, "GET"): print("FAIL: Getting VSX failed with status code %d" % response.status_code) if response.status_code == 400: print("Possibly no VSX currently configured") else: print("SUCCESS: Getting VSX information succeeded") result = response.json() return result
def delete_port(port_name, **kwargs): """ Perform a DELETE call to delete a Port table entry. :param port_name: Port table entry name :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ port_name_percents = common_ops._replace_special_characters(port_name) ports_list = get_all_ports(**kwargs) if "/rest/v1/system/ports/%s" % port_name_percents in ports_list: target_url = kwargs["url"] + "system/ports/%s" % port_name_percents response = kwargs["s"].delete(target_url, verify=False) if not common_ops._response_ok(response, "DELETE"): print("FAIL: Deleting Port '%s' failed with status code %d" % (port_name, response.status_code)) else: print("SUCCESS: Deleting Port '%s' succeeded" % port_name) else: print("SUCCESS: No need to remove Port '%s' since it doesn't exist" % port_name)
def _add_vrf(vrf_name, route_distinguisher=None, vrf_type="user", **kwargs): """ Perform a POST call to create a new VRF, and add a route distinguisher if desired. :param vrf_name: name of VRF :param route_distinguisher: Optional route distinguisher to add. Defaults to nothing if not specified. :param vrf_type: Optional VRF type. Defaults to "user" if not specified. :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ vrfs_dict = get_all_vrfs(**kwargs) if vrf_name not in vrfs_dict: vrf_data = {"name": vrf_name, "type": vrf_type} if route_distinguisher is not None: vrf_data["rd"] = route_distinguisher target_url = kwargs["url"] + "system/vrfs" post_data = json.dumps(vrf_data, sort_keys=True, indent=4) response = kwargs["s"].post(target_url, data=post_data, verify=False) if not common_ops._response_ok(response, "POST"): print("FAIL: Creating new VRF '%s' failed with status code %d" % (vrf_name, response.status_code)) else: print("SUCCESS: Creating new VRF '%s' succeeded" % vrf_name) else: print("SUCCESS: No need to create VRF '%s' since it already exists" % vrf_name)
def add_l3_ipv4_port(port_name, ip_address=None, port_desc=None, port_admin_state="up", vrf="default", **kwargs): """ Perform a POST call to create a Port table entry for a physical L3 interface. If the port already exists, the function will enable routing on the port and update the IPv4 address if given. :param port_name: Alphanumeric Port name :param ip_address: IPv4 address to assign to the interface. Defaults to nothing if not specified. :param port_desc: Optional description for the interface. Defaults to nothing if not specified. :param port_admin_state: Optional administratively-configured state of the port. Defaults to "up" if not specified :param vrf: Name of the VRF to which the Port belongs. Defaults to "default" if not specified. :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ ports_list = get_all_ports(**kwargs) port_name_percents = common_ops._replace_special_characters(port_name) port_data = { "admin": port_admin_state, "interfaces": ["/rest/v1/system/interfaces/%s" % port_name_percents], "name": port_name, "routing": True, "vrf": "/rest/v1/system/vrfs/%s" % vrf } if port_desc is not None: port_data['description'] = port_desc if ip_address is not None: port_data['ip4_address'] = ip_address if "/rest/v1/system/ports/%s" % port_name_percents not in ports_list: target_url = kwargs["url"] + "system/ports" payload_data = json.dumps(port_data, sort_keys=True, indent=4) response = kwargs["s"].post(target_url, data=payload_data, verify=False) if not common_ops._response_ok(response, "POST"): print( "FAIL: Adding IPv4 Port table entry '%s' failed with status code %d" % (port_name, response.status_code)) else: print("SUCCESS: Adding IPv4 Port table entry '%s' succeeded" % port_name) else: update_port_ipv4(port_name, ip_address, port_admin_state, vrf, **kwargs)
def add_vlan_port(vlan_port_name, vlan_id, ipv4=None, vrf_name="default", vlan_port_desc=None, port_admin_state="up", **kwargs): """ Perform a POST call to create a logical VLAN Port as part of SVI creation. :param vlan_port_name: Alphanumeric Port name :param vlan_id: Numeric ID of VLAN :param ipv4: Optional IPv4 address to assign to the interface.Defaults to nothing if not specified. :param vrf_name: VRF to attach the SVI to. Defaults to "default" if not specified :param vlan_port_desc: Optional description for the interface. Defaults to nothing if not specified. :param port_admin_state: Optional administratively-configured state of the port. Defaults to "up" if not specified :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ ports_list = get_all_ports(**kwargs) if "/rest/v1/system/ports/%s" % vlan_port_name not in ports_list: vlan_port_data = { "admin": port_admin_state, "name": vlan_port_name, "vrf": "/rest/v1/system/vrfs/%s" % vrf_name, "vlan_tag": "/rest/v1/system/vlans/%s" % vlan_id } if vlan_port_desc is not None: vlan_port_data['description'] = vlan_port_desc if ipv4 is not None: vlan_port_data['ip4_address'] = ipv4 target_url = kwargs["url"] + "system/ports" post_data = json.dumps(vlan_port_data, sort_keys=True, indent=4) response = kwargs["s"].post(target_url, data=post_data, verify=False) if not common_ops._response_ok(response, "POST"): print( "FAIL: Adding Port table entry '%s' for SVI failed with status code %d" % (vlan_port_name, response.status_code)) else: print("SUCCESS: Adding Port table entry '%s' for SVI succeeded" % vlan_port_name) else: print( "SUCCESS: No need to create VLAN Port '%s' since it already exists" % vlan_port_name)
def _port_set_untagged_vlan(l2_port_name, vlan_id, **kwargs): """ Perform GET and PUT/POST calls to set a VLAN on an access port :param l2_port_name: L2 interface's Port table entry name :param vlan_id: Numeric ID of VLAN to set on access port :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ l2_port_name_percents = common_ops._replace_special_characters( l2_port_name) port_data = get_port(l2_port_name_percents, depth=0, selector="configuration", **kwargs) port_data.pop('name', None) port_data.pop('origin', None) port_data.pop('vrf', None) port_data['vlan_mode'] = "access" port_data['vlan_tag'] = "/rest/v1/system/vlans/%s" % vlan_id port_data['routing'] = False target_url = kwargs["url"] + "system/ports/%s" % l2_port_name_percents put_data = json.dumps(port_data, sort_keys=True, indent=4) response = kwargs["s"].put(target_url, data=put_data, verify=False) if not (common_ops._response_ok(response, "PUT") or common_ops._response_ok(response, "POST")): print( "FAIL: Setting Port '%s' access VLAN to VLAN ID '%d' failed with status code %d" % (l2_port_name, vlan_id, response.status_code)) else: print( "SUCCESS: Setting Port '%s' access VLAN to VLAN ID '%d' succeeded" % (l2_port_name, vlan_id))
def _update_vsx_interface_vlan(vlan_id, active_forwarding, vsx_sync, act_gw_mac, act_gw_ip, **kwargs): """ Perform PUT calls on a VLAN interface to configure VSX IPv4 settings :param vlan_id: Numeric ID of VLAN to that will be configured :param active_forwarding: True or False Boolean to set VSX active forwarding :param vsx_sync: Set of alphanumeric values to enable VSX configuration synchronization. The options are any combination of 'active-gateways', 'irdp', and 'policies' :param act_gw_mac: Alphanumeric value of the Virtual MAC address for the interface active gateway :param act_gw_ip: Alphanumeric value of the Virtual IP address for the interface active gateway :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ ints_list = interface.get_all_interfaces(**kwargs) vlan_name = "vlan" + str(vlan_id) if vlan_name not in ints_list: print( "FAIL: Adding VSX information to VLAN Interface '%d' failed because " "VLAN Interface doesn't exist" % vlan_id) else: interface_vsx_data = interface.get_interface(vlan_name, depth=2, selector="writable", **kwargs) vsx_sync_set = [] if "active-gateways" in vsx_sync: vsx_sync_set.append("^vsx_virtual.*") if "irdp" in vsx_sync: vsx_sync_set.append(".irdp.*") if "policies" in vsx_sync: vsx_sync_set.append("^policy.*") interface_vsx_data["vsx_active_forwarding_enable"] = active_forwarding interface_vsx_data["vsx_sync"] = vsx_sync_set interface_vsx_data["vsx_virtual_gw_mac_v4"] = act_gw_mac interface_vsx_data["vsx_virtual_ip4"] = [act_gw_ip] target_url = kwargs["url"] + "system/interfaces/" + vlan_name put_data = json.dumps(interface_vsx_data, sort_keys=True, indent=4) response = kwargs["s"].put(target_url, data=put_data, verify=False) if not common_ops._response_ok(response, "PUT"): print( "FAIL: Adding VSX information to VLAN Interface '%d' failed with status code %d" % (vlan_id, response.status_code)) else: print( "SUCCESS: Adding VSX information to VLAN Interface '%d' succeeded" % vlan_id)
def add_vrf_address_family(vrf_name, family_type="ipv4_unicast", export_target=[], import_targets=[], **kwargs): """ Perform a POST call to create a new VRF, and add a route distinguisher if desired. Note that this functions has logic that works for both v1 and v10.04 :param vrf_name: Alphanumeric name of VRF :param family_type: Alphanumeric type of the Address Family. The options are 'ipv4_unicast' and 'ipv6_unicast'. The default value is set to 'ipv4_unicast'. :param export_target: Optional list of export route targets. :param import_targets: Optional list of import route targets :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ vrf_list = get_all_vrfs(**kwargs) if family_type == "ipv4-unicast": family_type = "ipv4_unicast" elif family_type == "ipv6-unicast": family_type = "ipv6_unicast" if family_type not in ['ipv4_unicast', 'ipv6_unicast']: raise Exception("ERROR: family_type should be 'ipv4_unicast', or 'ipv6_unicast'") if kwargs["url"].endswith("/v1/"): vrf_check = "/rest/v1/system/vrfs/%s" % vrf_name else: # Else logic designed for v10.04 and later vrf_check = vrf_name if vrf_check in vrf_list: address_family_data = { "address_family": family_type, "export_route_targets": export_target, "import_route_targets": import_targets, "route_map": {} } target_url = kwargs["url"] + "system/vrfs/%s/vrf_address_families" % vrf_name post_data = json.dumps(address_family_data, sort_keys=True, indent=4) response = kwargs["s"].post(target_url, data=post_data, verify=False) if not common_ops._response_ok(response, "POST"): print("FAIL: Creating '%s' Address Family on VRF '%s' failed with status code %d" % (family_type, vrf_name, response.status_code)) else: print("SUCCESS: Creating '%s' Address Family on VRF '%s' succeeded" % (family_type, vrf_name)) else: print("FAIL: Cannot add Address Family to VRF '%s' since the VRF has not been created yet" % vrf_name)
def get_arp_entries(vrf_name, **kwargs): """ Perform a GET call on Neighbors table to get ARP entries :param vrf_name: Alphanumeric name of VRF :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: List of dictionaries each containing one ARP entry """ queries = {"depth": 1} target_url = kwargs["url"] + "system/vrfs/%s/neighbors" % vrf_name response = kwargs["s"].get(target_url, verify=False, params=queries, timeout=2) if not common_ops._response_ok(response, "GET"): print( "FAIL: Getting Neighbors table entries failed with status code %d" % response.status_code) else: print("SUCCESS: Getting Neighbors table entries succeeded") neighbor_info_list = response.json() arp_entries_list = [] for neighbor_info in neighbor_info_list: arp_entry = { "IPv4 Address": neighbor_info['ip_address'], "MAC Address": neighbor_info['mac'], # For port and physical port: split string by '/', take last block, and replace any '%' characters "Port": common_ops._replace_percents( (neighbor_info['port'].split('/'))[-1]), "State": neighbor_info['state'] } if 'phy_port' in neighbor_info: arp_entry['Physical Port'] = common_ops._replace_percents( (neighbor_info['phy_port'].split('/'))[-1]) arp_entries_list.append(arp_entry) return arp_entries_list
def _update_port_acl_in_v1(interface_name, acl_name, list_type, **kwargs): """ Perform GET and PUT calls to apply ACL on an interface. This function specifically applies an ACL to Ingress traffic of the interface :param interface_name: Alphanumeric String that is the name of the interface on which the ACL is applied to :param acl_name: Alphanumeric String that is the name of the ACL :param list_type: Alphanumeric String of ipv4 or ipv6 to specify the type of ACL :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ port_name_percents = common_ops._replace_special_characters(interface_name) port_data = port.get_port(port_name_percents, depth=0, selector="configuration", **kwargs) # must remove these fields from the data since they can't be modified port_data.pop('name', None) port_data.pop('origin', None) acl_url = "/rest/v1/system/acls/%s/%s" % (acl_name, list_type) if list_type is "ipv6": port_data['aclv6_in_cfg'] = acl_url port_data['aclv6_in_cfg_version'] = random.randint( -9007199254740991, 9007199254740991) elif list_type is "ipv4": port_data['aclv4_in_cfg'] = acl_url port_data['aclv4_in_cfg_version'] = random.randint( -9007199254740991, 9007199254740991) target_url = kwargs["url"] + "system/ports/%s" % port_name_percents put_data = json.dumps(port_data, sort_keys=True, indent=4) response = kwargs["s"].put(target_url, data=put_data, verify=False) if not common_ops._response_ok(response, "PUT"): print( "FAIL: Applying ACL '%s' to Ingress of Interface '%s' failed with status code %d" % (acl_name, interface_name, response.status_code)) else: print( "SUCCESS: Applying ACL '%s' to Ingress of Interface '%s' succeeded" % (acl_name, interface_name))
def logout(**kwargs): """ Perform a POST call to logout and end session. :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: Nothing """ response = kwargs["s"].post(kwargs["url"] + "logout", verify=False) # Response OK check needs to be passed "PUT" since this POST call returns 200 instead of conventional 201 if not common_ops._response_ok(response, "PUT"): print("FAIL: Logout failed with status code %d" % response.status_code) else: print("SUCCESS: Logout succeeded")