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: True if successful, False otherwise """ 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")): logging.warning( "FAIL: Setting Port '%s' access VLAN to VLAN ID '%d' failed with status code %d: %s" % (l2_port_name, vlan_id, response.status_code, response.text)) return False else: logging.info( "SUCCESS: Setting Port '%s' access VLAN to VLAN ID '%d' succeeded" % (l2_port_name, vlan_id)) return True
def _update_l2_lag_interface(name, mc_lag=False, fallback_enabled=False, **kwargs): """ Perform GET and PUT calls to update the Interface table entry for L2 LAG interface. :param name: Alphanumeric name of LAG Port :param mc_lag: Boolean to determine if the LAG is multi-chassis. Defaults to False if not specified. :param fallback_enabled: Boolean to determine if the LAG uses LACP fallback. Defaults to False if not specified. :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: True if successful, False otherwise """ int_name_percents = common_ops._replace_special_characters(name) int_data = interface.get_interface(name, 1, "writable", **kwargs) 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['vlan_tag']: # Convert the dictionary to a URI string int_data['vlan_tag'] = common_ops._dictionary_to_string(int_data['vlan_tag']) int_data['other_config']['mclag_enabled'] = mc_lag int_data['other_config']['lacp-fallback'] = fallback_enabled 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"): logging.warning("FAIL: Updating LAG Interface entry '%s' " "failed with status code %d: %s" % (name, response.status_code, response.text)) return False else: logging.info("SUCCESS: Updating LAG Interface entry '%s' " "succeeded" % name) return True
def _update_ospf_interface_type_v1(vrf, ospf_id, interface_name, interface_type, **kwargs): """ Perform PUT calls to update the type of OSPFv2 Interface given, as well as enable routing on the interface :param vrf: Alphanumeric name of the VRF the OSPF ID belongs to :param ospf_id: OSPF process ID between numbers 1-63 :param interface_name: Alphanumeric name of the interface that will be attached to the OSPF area :param interface_type: Alphanumeric type of OSPF interface. The options are 'broadcast', 'loopback', 'nbma', 'none', 'pointomultipoint', 'pointopoint', and 'virtuallink' :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: True if successful, False otherwise """ ports_list = port.get_all_ports(**kwargs) port_name_percents = common_ops._replace_special_characters(interface_name) if "/rest/v1/system/ports/%s" % port_name_percents not in ports_list: port.add_l3_ipv4_port(interface_name, vrf=vrf, **kwargs) port_data = port.get_port(interface_name, 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) port_data['ospf_if_type'] = "ospf_iftype_%s" % interface_type port_data['routing'] = True port_data['vrf'] = "/rest/v1/system/vrfs/" + vrf 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"): logging.warning("FAIL: Updating OSPF %s interface type for Port '%s' failed with status code %d: %s" % (ospf_id, interface_name, response.status_code, response.text)) return False else: logging.info("SUCCESS: Updating OSPF %s interface type for Port '%s' succeeded" % (ospf_id, interface_name)) return True
def _delete_vlan_port(l2_port_name, vlan_id, **kwargs): """ Perform GET and PUT calls to remove a VLAN from a trunk port :param l2_port_name: L2 interface's Port table entry name :param vlan_id: Numeric ID of VLAN to remove from trunk port :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: True if successful, False otherwise """ l2_port_name_percents = common_ops._replace_special_characters( l2_port_name) port_data = get_port(l2_port_name, depth=0, selector="configuration", **kwargs) port_data.pop('name', None) port_data.pop('origin', None) port_data.pop('vrf', None) if "/rest/v1/system/vlans/%s" % vlan_id in port_data['vlan_trunks']: # remove vlan from 'vlan_trunks' port_data['vlan_trunks'].remove("/rest/v1/system/vlans/%s" % vlan_id) 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"): logging.warning( "FAIL: Removing VLAN ID '%d' from Port '%s' trunk failed with status code %d: %s" % (vlan_id, l2_port_name, response.status_code, response.text)) return False else: logging.info( "SUCCESS: Removing VLAN ID '%d' from Port '%s' trunk succeeded" % (vlan_id, l2_port_name)) return True
def update_port_ipv6(port_name, ip_address, addr_type="global-unicast", **kwargs): """ Perform a POST call to create an IPv6 address entry to update an L3 interface's ipv6 address :param port_name: Alphanumeric name of the Port :param ipv6: IPv6 address to associate with the Port :param addr_type: Type of IPv6 address. Defaults to "global-unicast" if not specified. :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: True if successful, False otherwise """ port_name_percents = common_ops._replace_special_characters(port_name) ipv6_data = { "address": ip_address, "node_address": True, "origin": "configuration", "ra_prefix": True, "route_tag": 0, "type": addr_type } target_url = kwargs[ "url"] + "system/ports/%s/ip6_addresses" % port_name_percents post_data = json.dumps(ipv6_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"): logging.warning( "FAIL: Creating IPv6 address to update Port '%s' to '%s' failed with status code %d: %s" % (port_name, ip_address, response.status_code, response.text)) return False else: logging.info( "SUCCESS: Creating IPv6 address to update Port '%s' to '%s' succeeded" % (port_name, ip_address)) return True
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: True if successful, False otherwise """ 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"): logging.warning( "FAIL: Clearing Loop-protect options on Port '%s' failed with status code %d: %s" % (port_name, response.status_code, response.text)) return False else: logging.info( "SUCCESS: Clearing the Loop-protect options on Port '%s' succeeded" % (port_name)) return True
def _get_port(port_name, depth=0, selector=None, **kwargs): """ Perform a GET call to retrieve data for a Port table entry :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: Dictionary containing port data """ if selector not in [ 'configuration', 'status', 'statistics', 'writable', None ]: raise Exception( "ERROR: Selector should be 'configuration', 'status', 'statistics', or 'writable'" ) payload = {"depth": depth, "selector": selector} port_name_percents = common_ops._replace_special_characters(port_name) target_url = kwargs["url"] + "system/ports/%s" % port_name_percents response = kwargs["s"].get(target_url, verify=False, params=payload, timeout=2) port_name = common_ops._replace_percents(port_name_percents) if not common_ops._response_ok(response, "GET"): logging.warning( "FAIL: Getting Port table entry '%s' failed with status code %d: %s" % (port_name, response.status_code, response.text)) output = {} else: logging.info("SUCCESS: Getting Port table entry '%s' succeeded" % port_name) output = response.json() return output
def _update_ospf_interface_authentication(vrf, ospf_id, interface_name, auth_type, digest_key, auth_pass, **kwargs): """ Perform PUT calls to update an Interface with OSPF to have authentication :param vrf: Alphanumeric name of the VRF the OSPF ID belongs to :param ospf_id: OSPF process ID between numbers 1-63 :param interface_name: Alphanumeric name of the interface that will be attached to the OSPF area :param auth_type: Alphanumeric type of authentication, chosen between 'md5', 'null', and 'text' :param digest_key: Integer between 1-255 that functions as the digest key for the authentication method :param auth_pass: Alphanumeric text for the authentication password. Note that this will be translated to a base64 String in the configuration and json. :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: True if successful, False otherwise """ interface_name_percents = common_ops._replace_special_characters(interface_name) interface_data = interface.get_interface(interface_name, depth=1, selector="writable", **kwargs) interface_data['ospf_auth_type'] = auth_type interface_data['ospf_auth_md5_keys'] = {str(digest_key): auth_pass} interface_data['ospf_if_type'] = "ospf_iftype_broadcast" interface_data['routing'] = True interface_data['vrf'] = "/rest/v10.04/system/vrfs/%s" % vrf target_url = kwargs["url"] + "system/interfaces/%s" % interface_name_percents put_data = json.dumps(interface_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"): logging.warning("FAIL: Updating OSPF %s Authentication for Port '%s' failed with status code %d: %s" % (ospf_id, interface_name, response.status_code, response.text)) return False else: logging.info("SUCCESS: Updating OSPF %s Authentication for Port '%s' succeeded" % (ospf_id, interface_name)) return True
def _update_port_loop_protect_v1(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: True if successful, False otherwise """ 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) port_data['loop_protect_enable'] = True # make interface L2 port_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: port_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/v1/system/vlans/%s" % vlan if vlan_url not in port_data['loop_protect_vlan']: port_data['loop_protect_vlan'].append(vlan_url) vlan_output += (" " + str(vlan)) vlan_output += "] " 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"): logging.warning( "FAIL: Applying Loop-protect to Interface '%s'%s%s failed with status code %d: %s" % (interface_name, action_output, vlan_output, response.status_code, response.text)) return False else: logging.info( "SUCCESS: Applying Loop-protect to Interface '%s'%s%s succeeded" % (interface_name, action_output, vlan_output)) return True
def _create_l2_lag_interface_v1(name, phys_ports, lacp_mode="passive", mc_lag=False, fallback_enabled=False, vlan_ids_list=[], desc=None, admin_state="up", **kwargs): """ Perform a POST call to create a Port table entry for L2 LAG interface. :param name: Alphanumeric name of LAG Port :param phys_ports: List of physical ports to aggregate (e.g. ["1/1/1", "1/1/2", "1/1/3"]) :param lacp_mode: Should be either "passive" or "active." Defaults to "passive" if not specified. :param mc_lag: Boolean to determine if the LAG is multi-chassis. Defaults to False if not specified. :param fallback_enabled: Boolean to determine if the LAG uses LACP fallback. Defaults to False if not specified. :param vlan_ids_list: Optional list of integer VLAN IDs to add as trunk VLANS. Defaults to empty list if not specified. :param desc: Optional description for the interface. Defaults to nothing if not specified. :param 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: True if successful, False otherwise """ ports_list = port.get_all_ports(**kwargs) port_name_percents = common_ops._replace_special_characters(name) if "/rest/v1/system/ports/%s" % port_name_percents not in ports_list: # Extract LAG ID from LAG name lag_id = int(re.search('\d+', name).group()) # For each port, add LAG ID to the Interface table entry, and delete the Port table entry for phys_port in phys_ports: interface.add_port_to_lag(phys_port, lag_id, **kwargs) interfaces = ["/rest/v1/system/interfaces/%s" % common_ops._replace_special_characters(phys_port) for phys_port in phys_ports] port_data = {"admin": admin_state, "interfaces": interfaces, "name": name, "routing": False, "vlan_trunks": ["/rest/v1/system/vlans/%d" % vlan_id for vlan_id in vlan_ids_list], "lacp": lacp_mode, "other_config": { "mclag_enabled": mc_lag, "lacp-fallback": fallback_enabled }, "vlan_mode": "native-untagged", "vlan_tag": "/rest/v1/system/vlans/1" } if desc is not None: port_data['description'] = desc target_url = kwargs["url"] + "system/ports" post_data = json.dumps(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"): logging.warning("FAIL: Adding Port table entry '%s' failed with status code %d: %s" % (name, response.status_code, response.text)) return False else: logging.info("SUCCESS: Adding Port table entry '%s' succeeded" % name) return True else: logging.info("SUCCESS: No need to add Port table entry '%s' because it already exists" % name) return True
def _create_l3_lag_interface(name, phys_ports, ipv4, lacp_mode="passive", mc_lag=False, fallback_enabled=False, desc=None, admin_state="up", vrf="default", **kwargs): """ Perform a POST call to create a Port table entry for L3 LAG interface. :param name: Alphanumeric Port name :param phys_ports: List of physical ports to aggregate (e.g. ["1/1/1", "1/1/2", "1/1/3"]) :param ipv4: IPv4 address to assign to the interface. Defaults to nothing if not specified. :param lacp_mode: Should be either "passive" or "active." Defaults to "passive" if not specified. :param mc_lag: Boolean to determine if the LAG is multi-chassis. Defaults to False if not specified. :param fallback_enabled: Boolean to determine if the LAG uses LACP fallback. Defaults to False if not specified. :param desc: Optional description for the interface. Defaults to nothing if not specified. :param 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: True if successful, False otherwise """ ints_dict = interface.get_all_interfaces(**kwargs) if name not in ints_dict: # Extract LAG ID from LAG name lag_id = int(re.search('\d+', name).group()) # For each port, add LAG ID to the Interface table entry, and delete the Port table entry for phys_port in phys_ports: interface.add_port_to_lag(phys_port, lag_id, **kwargs) interfaces = ["/rest/v10.04/system/interfaces/%s" % common_ops._replace_special_characters(phys_port) for phys_port in phys_ports] int_data = {"admin": admin_state, "interfaces": interfaces, "name": name, "type": "lag", "vrf": "/rest/v10.04/system/vrfs/%s" % vrf, "routing": True, "ip4_address": ipv4, "lacp": lacp_mode, # "other_config": { # "mclag_enabled": mc_lag, # "lacp-fallback": fallback_enabled # } } """commented out the other_config since it causes error""" if desc is not None: int_data['description'] = desc target_url = kwargs["url"] + "system/interfaces" post_data = json.dumps(int_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"): logging.warning("FAIL: Adding Interface table entry '%s' failed with status code %d: %s" % (name, response.status_code, response.text)) return False else: logging.info("SUCCESS: Adding Interface table entry '%s' succeeded" % name) return True else: logging.info("SUCCESS: No need to add Interface table entry '%s' because it already exists" % name) return True
def _port_set_native_vlan(l2_port_name, vlan_id, tagged=True, **kwargs): """ Perform GET and PUT/POST calls to set a VLAN to be the native VLAN on the trunk. Also gives the option to set the VLAN as tagged. :param l2_port_name: L2 interface's Port table entry name :param vlan_id: Numeric ID of VLAN to add to trunk port :param tagged: Boolean to determine if the native VLAN will be set as the tagged VLAN. If False, the VLAN will be set as the native untagged VLAN :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: True if successful, False otherwise """ if tagged: vlan_mode = "native-tagged" else: vlan_mode = "native-untagged" # need to create port resource for physical port if it doesn't exist ports_list = get_all_ports(**kwargs) l2_port_name_percents = common_ops._replace_special_characters( l2_port_name) if "/rest/v1/system/ports/%s" % l2_port_name_percents not in ports_list: # if Port table entry doesn't exist, create it port_data = { "name": l2_port_name, "interfaces": ["/rest/v1/system/interfaces/%s" % l2_port_name_percents], "vlan_mode": vlan_mode, "vlan_tag": "/rest/v1/system/vlans/%s" % vlan_id, "vlan_trunks": [], "routing": False } target_url = kwargs["url"] + "system/ports" post_data = json.dumps(port_data, sort_keys=True, indent=4) response = kwargs["s"].post(target_url, data=post_data, verify=False) else: # otherwise just update the physical port 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_tag'] = "/rest/v1/system/vlans/%s" % vlan_id port_data['routing'] = False port_data['vlan_mode'] = vlan_mode if (port_data['vlan_trunks']) and ("/rest/v1/system/vlans/%s" % vlan_id not in port_data['vlan_trunks']): port_data['vlan_trunks'].append("/rest/v1/system/vlans/%s" % vlan_id) 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")): logging.warning( "FAIL: Setting native VLAN ID '%d' to Port '%s' failed with status code %d: %s" % (vlan_id, l2_port_name, response.status_code, response.text)) return False else: logging.info( "SUCCESS: Setting native VLAN ID '%d' to Port '%s' succeeded" % (vlan_id, l2_port_name)) return True
def _port_add_vlan_trunks(l2_port_name, vlan_trunk_ids=[], **kwargs): """ Perform GET and PUT/POST calls to add specified VLANs to a trunk port. By default, this will also set the port to have 'no routing' and if there is not a native VLAN, will set the native VLAN to VLAN 1. :param l2_port_name: L2 interface's Port table entry name :param vlan_trunk_ids: List of VLANs to specify as allowed on the trunk port. If empty, the interface will allow all VLANs on the trunk. :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: True if successful, False otherwise """ # need to create port resource for physical port if it doesn't exist ports_list = get_all_ports(**kwargs) l2_port_name_percents = common_ops._replace_special_characters( l2_port_name) trunk_list = [] for x in vlan_trunk_ids: trunk_list.append("/rest/v1/system/vlans/%d" % x) if "/rest/v1/system/ports/%s" % l2_port_name_percents not in ports_list: # if Port table entry doesn't exist, create it port_data = { "name": l2_port_name, "interfaces": ["/rest/v1/system/interfaces/%s" % l2_port_name_percents], "vlan_mode": "native-untagged", "vlan_tag": "/rest/v1/system/vlans/1", "vlan_trunks": trunk_list, "routing": False } target_url = kwargs["url"] + "system/ports" post_data = json.dumps(port_data, sort_keys=True, indent=4) response = kwargs["s"].post(target_url, data=post_data, verify=False) else: # otherwise just update the physical port 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) if 'vlan_tag' not in port_data: port_data['vlan_tag'] = "/rest/v1/system/vlans/1" if 'vlan_mode' not in port_data: port_data['vlan_mode'] = "native-untagged" port_data['routing'] = False if not trunk_list: port_data['vlan_trunks'] = [] else: for y in trunk_list: if y not in port_data['vlan_trunks']: port_data['vlan_trunks'].append(y) 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")): logging.warning( "FAIL: Adding VLANs '%s' to Port '%s' trunk failed with status code %d: %s" % (vlan_trunk_ids, l2_port_name, response.status_code, response.text)) return False else: logging.info( "SUCCESS: Adding VLANs '%s' to Port '%s' trunk succeeded" % (vlan_trunk_ids, l2_port_name)) return True
def add_l3_ipv6_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 perform a PUT call to update the Port table entry to enable routing on the port and update the IPv6 address if given. :param port_name: Alphanumeric Port name :param ip_address: IPv6 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: True if successful, False otherwise """ 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 "/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"): logging.warning( "FAIL: Adding L3 IPv6 Port table entry '%s' failed with status code %d: %s" % (port_name, response.status_code, response.text)) return False else: logging.info( "SUCCESS: Adding L3 IPv6 Port table entry '%s' succeeded" % port_name) # IPv6 defaults ipv6_data = { "address": ip_address, "node_address": True, "origin": "configuration", "ra_prefix": True, "route_tag": 0, "type": "global-unicast" } target_url = kwargs[ "url"] + "system/interfaces/%s/ip6_addresses" % port_name_percents post_data = json.dumps(ipv6_data, sort_keys=True, indent=4) response = kwargs["s"].put(target_url, data=post_data, verify=False) if not common_ops._response_ok(response, "POST"): logging.warning( "FAIL: Final configuration of L3 IPv6 Port table entry '%s' failed with status code %d: %s" % (port_name, response.status_code, response.text)) return False else: logging.info( "SUCCESS: Final configuration of L3 IPv6 Port table entry '%s' succeeded" % port_name) return True else: port_data.pop( 'name', None ) # must remove this item from the json since name can't be modified target_url = kwargs["url"] + "system/ports/%s" % port_name_percents 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"): logging.warning( "FAIL: Updating L3 IPv6 Port table entry '%s' failed with status code %d: %s" % (port_name, response.status_code, response.text)) return False else: logging.info( "SUCCESS: Updating L3 IPv6 Port table entry '%s' succeeded" % port_name) return update_port_ipv6(port_name, ip_address, **kwargs)
def create_bgp_neighbors(vrf_name, asn, group_ip, family_type="l2vpn_evpn", reflector=False, send_community=False, local_interface="", **kwargs): """ Perform a POST call to create BGP neighbors to the associated BGP ASN. With l2vpn_evpn being True, this will also apply EVPN settings to the BGP neighbor configurations. Note that this functions has logic that works for both v1 and v10.04 :param vrf_name: Alphanumeric name of the VRF the BGP ASN belongs to :param asn: Integer that represents the Autonomous System Number :param group_ip: IPv4 address or name of group of the neighbors that functions as the BGP Router link :param family_type: Alphanumeric to specify what type of neighbor settings to configure. The options are 'l2vpn-evpn', 'ipv4-unicast', or 'ipv6-unicast'. When setting to l2vpn-evpn, the neighbor configurations also will add route-reflector-client and send-community settings. :param reflector: Boolean value to determine whether this neighbor has route reflector enabled. Default is False. :param send_community: Boolean value to determine whether this neighbor has send-community enabled. Default is False. :param local_interface: Optional alphanumeric to specify which interface the neighbor will apply to. :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: True if successful, False otherwise """ if family_type not in ['l2vpn-evpn', 'ipv4-unicast', 'ipv6-unicast']: raise Exception("ERROR: family_type should be 'l2vpn-evpn', 'ipv4-unicast', or 'ipv6-unicast'") neighbor_list = get_bgp_neighbors_list(vrf_name, asn, **kwargs) if group_ip not in neighbor_list: bgp_data = { "ip_or_group_name": group_ip, "is_peer_group": False, "remote_as": asn, "shutdown": False, "activate": { "ipv4-unicast": False, "ipv6-unicast": False, "l2vpn-evpn": False }, "next_hop_unchanged": { "l2vpn-evpn": False }, "route_reflector_client": { "ipv4-unicast": False, "ipv6-unicast": False, "l2vpn-evpn": False }, "send_community": { "ipv4-unicast": "none", "ipv6-unicast": "none", "l2vpn-evpn": "none" } } if local_interface: int_percents = common_ops._replace_special_characters(local_interface) if kwargs["url"].endswith("/v1/"): bgp_data.update({'local_interface': "/rest/v1/system/ports/%s" % int_percents}) else: # Else logic designed for v10.04 and later bgp_data.update({'local_interface': "/rest/v10.04/system/interfaces/%s" % int_percents}) bgp_data['activate'][family_type] = True if send_community: bgp_data['send_community'][family_type] = "both" if reflector: bgp_data['route_reflector_client'][family_type] = reflector target_url = kwargs["url"] + "system/vrfs/%s/bgp_routers/%s/bgp_neighbors" % (vrf_name, asn) post_data = json.dumps(bgp_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"): logging.warning("FAIL: Creating BGP Neighbor for ASN '%s' on interface %s failed with status code %d: %s" % (asn, local_interface, response.status_code, response.text)) return False else: logging.info("SUCCESS: Creating BGP Neighbor for ASN '%s' succeeded on interface %s" % (asn, local_interface)) return True else: logging.info("SUCCESS: BGP Neighbor already exists for ASN '%s' on interface '%s'." % (asn, local_interface)) return True
def _create_vsx(role, isl_port, keepalive_peer, keepalive_src, keepalive_vrf, vsx_mac, keepalive_port=7678, **kwargs): """ Perform a POST call to create VSX commands. :param role: Alphanumeric role that the system will be in the VSX pair. The options are "primary" or "secondary" :param isl_port: Alphanumeric name of the interface that will function as the inter-switch link :param keepalive_peer: Alphanumeric IP address of the VSX Peer that will be reached as the keepalive connection. :param keepalive_src: Alphanumeric IP address on the switch that will function as the keepalive connection source. :param keepalive_vrf: Alphanumeric name of the VRF that the keepalive connection will reside on. :param vsx_mac: Alphanumeric MAC address that will function as the VSX System MAC. :param kwargs: keyword s: requests.session object with loaded cookie jar keyword url: URL in main() function :return: True if successful, False otherwise """ system_info_dict = system.get_system_info(**kwargs) if system_info_dict['vsx'] is not None: logging.warning( "FAIL: Creating VSX Role '%s' on vrf %s. There is already an existing VSX setup." % (role, keepalive_vrf)) return False else: if role not in ['primary', 'secondary']: raise Exception( "ERROR: VSX role should be 'primary' or 'secondary'") # Checks if the ISL Port is a physical interface or a Lag. If an interface, replace the slashes if isl_port[0].isdigit(): isl_port = common_ops._replace_special_characters(isl_port) isl_port_uri = "/rest/v10.04/system/interfaces/" + isl_port ip_src_subnet = keepalive_src.find('/') ip_peer_subnet = keepalive_peer.find('/') if ip_src_subnet >= 0: keepalive_src = keepalive_src[0:ip_src_subnet] if ip_peer_subnet >= 0: keepalive_peer = keepalive_peer[0:ip_peer_subnet] vsx_data = { "config_sync_disable": False, "config_sync_features": [], "device_role": role, "isl_port": isl_port_uri, "isl_timers": { "hello_interval": 1, "hold_time": 0, "peer_detect_interval": 300, "timeout": 20 }, "keepalive_peer_ip": keepalive_peer, "keepalive_src_ip": keepalive_src, "keepalive_timers": { "dead_interval": 3, "hello_interval": 1 }, "keepalive_udp_port": keepalive_port, "keepalive_vrf": { keepalive_vrf: "/rest/v10.04/system/vrfs/" + keepalive_vrf, }, "linkup_delay_timer": 180, "split_recovery_disable": False, "system_mac": vsx_mac } target_url = kwargs["url"] + "system/vsx" post_data = json.dumps(vsx_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"): logging.warning( "FAIL: Creating VSX Role '%s' on vrf %s failed with status code %d: %s" % (role, keepalive_vrf, response.status_code, response.text)) return False else: logging.info( "SUCCESS: Creating VSX Role '%s' succeeded on vrf %s" % (role, keepalive_vrf)) return True