From bfcfe572542a95db39e74fbf06cd1cd72b10610e Mon Sep 17 00:00:00 2001 From: Per Abildgaard Toft Date: Wed, 24 May 2023 14:49:16 +0200 Subject: [PATCH 1/2] Fixed issue #49 Added support for IPv6 resouce pools when creating a new routing zone --- aos/blueprint.py | 17 +++++++++++++++++ docs/example-scripts/blueprint/routing_zone.md | 1 + 2 files changed, 18 insertions(+) diff --git a/aos/blueprint.py b/aos/blueprint.py index d367f48..15af3ad 100644 --- a/aos/blueprint.py +++ b/aos/blueprint.py @@ -1650,6 +1650,7 @@ def create_security_zone( vlan_id: int = None, vni_id: int = None, leaf_loopback_ip_pools: list = None, + leaf_loopback_ipv6_pools: list = None, dhcp_servers: list = None, timeout: int = 60, ): @@ -1748,6 +1749,22 @@ def create_security_zone( f"'{leaf_loopback_ip_pools}' to Security-zone " f"'{name}' in blueprint '{bp_id}'" ) + + # SZ leaf IPv6 loopback pool + if leaf_loopback_ipv6_pools: + group_path = requote_uri(f"sz:{sz.id},leaf_loopback_ips_ipv6") + self.apply_resource_groups( + bp_id=bp_id, + resource_type="ipv6", + group_name=group_path, + pool_ids=leaf_loopback_ipv6_pools, + ) + logger.info( + f"Applying '{group_name}' resource IPv6 pool " + f"'{leaf_loopback_ipv6_pools}' to Security-zone " + f"'{name}' in blueprint '{bp_id}'" + ) + # DHCP servers (relay) if dhcp_servers: dhcp = {"items": dhcp_servers} diff --git a/docs/example-scripts/blueprint/routing_zone.md b/docs/example-scripts/blueprint/routing_zone.md index 9215423..b193386 100644 --- a/docs/example-scripts/blueprint/routing_zone.md +++ b/docs/example-scripts/blueprint/routing_zone.md @@ -46,6 +46,7 @@ aos.blueprint.create_security_zone( bp_id=bp.id, name=sz_name, leaf_loopback_ip_pools=[leaf_lo_pool.id], + leaf_loopback_ipv6_pools=[leaf_lo_pool.id], dhcp_servers=[dhcp_rely_addr], ) ``` From c00e1267ac99c4d509244a0f0be4e2222e1ac218 Mon Sep 17 00:00:00 2001 From: Per Abildgaard Toft Date: Fri, 29 Sep 2023 10:28:55 +0200 Subject: [PATCH 2/2] Bugfixes --- aos/blueprint.py | 103 ++++++++++++++++++++++++----- aos/external_systems.py | 1 + tools/ct-template-generator.py | 60 +++++++++++++++++ tools/decode-nginx-request-body.py | 3 + 4 files changed, 149 insertions(+), 18 deletions(-) create mode 100644 tools/ct-template-generator.py create mode 100644 tools/decode-nginx-request-body.py diff --git a/aos/blueprint.py b/aos/blueprint.py index 15af3ad..ab1ca65 100644 --- a/aos/blueprint.py +++ b/aos/blueprint.py @@ -553,6 +553,8 @@ def is_task_active(self, bp_id: str, task_id: str) -> bool: ]: return True else: + if task["status"] in TaskStatus.failed.value: + print(json.dumps(task["detailed_status"]['errors'], indent=2)) return False else: @@ -833,6 +835,9 @@ def get_bp_nodes(self, bp_id: str, node_type: str = None): def get_bp_node_by_id(self, bp_id: str, node_id: str): return self.rest.json_resp_get(f"/api/blueprints/{bp_id}/nodes/{node_id}") + def get_bp_node_asn(self, bp_id: str, node_id: str): + return self.rest.json_resp_get(f"/api/blueprints/{bp_id}/systems/{node_id}/domain") + def get_bp_system_nodes(self, bp_id: str): return self.get_bp_nodes(bp_id, "system") @@ -969,6 +974,10 @@ def get_all_tor_nodes(self, bp_id): return nodes + def get_device_rendered_context(self, bp_id: str, node_id: str): + uri = f"/api/blueprints/{bp_id}/nodes/{node_id}/config-context" + return self.rest.json_resp_get(uri) + def create_switch_system_links(self, bp_id: str, data: dict): uri = f"/api/blueprints/{bp_id}/switch-system-links" @@ -1300,6 +1309,71 @@ def get_routing_policies(self, bp_id: str, bp_type="staging") -> Dict: f"/api/blueprints/{bp_id}/routing-policies?type={bp_type}" ) + def get_routing_policy(self, bp_id: str, rp_name: str) -> Dict: + for rp in self.get_routing_policies(bp_id)['items']: + if rp.get('label') == rp_name: + return rp + + def get_floating_ips(self, bp_id: str, vn_id: str) -> Dict: + all_floating_ips = self.rest.json_resp_get( + f"/api/blueprints/{bp_id}/floating-ips" + ) + filtered_results = list() + for i in all_floating_ips.get('items'): + print(i) + if i.get('virtual_network_id') == "WH2Qb8Yi2Dyot5A4qQc": + filtered_results.append(i) + return filtered_results + + def create_routing_policy(self, + bp_id: str, + label : str, + aggregate_prefixes: list = [], + description: str = "", + expect_default_ipv4_route: bool = False, + expect_default_ipv6_route: bool = False, + l2edge_subnets: bool = False, + l3edge_server_links: bool = False, + loopbacks: bool = False, + spine_leaf_links: bool = False, + spine_superspine_links: bool = False, + static_routes: bool = False, + extra_export_routes: list = [], + extra_import_routes: list = [], + import_policy: str = "default_only" + ): + #Example of extra_import_routes or extra_export_routes + # export_routes = [{'action': 'permit', + # 'ge_mask': None, + # 'le_mask': 32, + # 'prefix': '172.29.2.0/24'}] + + if import_policy not in ("extra_only", "default_only", "all"): + raise AosAPIResourceNotFound("Import policy not allowed") + + data = { + 'aggregate_prefixes': aggregate_prefixes, + 'description': description, + 'expect_default_ipv4_route': expect_default_ipv4_route, + 'expect_default_ipv6_route': expect_default_ipv6_route, + 'export_policy': { + 'l2edge_subnets': l2edge_subnets, + 'l3edge_server_links': l3edge_server_links, + 'loopbacks': loopbacks, + 'spine_leaf_links': spine_leaf_links, + 'spine_superspine_links': spine_superspine_links, + 'static_routes': static_routes, + }, + 'extra_export_routes': extra_export_routes, + 'extra_import_routes': extra_import_routes, + 'import_policy': import_policy, + 'label': label, + 'policy_type': 'user_defined'} + + rp_path = f"/api/blueprints/{bp_id}/routing-policies" + return self.rest.json_resp_post(rp_path, data=data) + + # External Routers def get_external_routers_all(self, bp_id: str): """ @@ -1650,7 +1724,6 @@ def create_security_zone( vlan_id: int = None, vni_id: int = None, leaf_loopback_ip_pools: list = None, - leaf_loopback_ipv6_pools: list = None, dhcp_servers: list = None, timeout: int = 60, ): @@ -1749,22 +1822,6 @@ def create_security_zone( f"'{leaf_loopback_ip_pools}' to Security-zone " f"'{name}' in blueprint '{bp_id}'" ) - - # SZ leaf IPv6 loopback pool - if leaf_loopback_ipv6_pools: - group_path = requote_uri(f"sz:{sz.id},leaf_loopback_ips_ipv6") - self.apply_resource_groups( - bp_id=bp_id, - resource_type="ipv6", - group_name=group_path, - pool_ids=leaf_loopback_ipv6_pools, - ) - logger.info( - f"Applying '{group_name}' resource IPv6 pool " - f"'{leaf_loopback_ipv6_pools}' to Security-zone " - f"'{name}' in blueprint '{bp_id}'" - ) - # DHCP servers (relay) if dhcp_servers: dhcp = {"items": dhcp_servers} @@ -2008,6 +2065,7 @@ def create_virtual_network( ipv6_gateway: str = None, tagged_ct: bool = False, untagged_ct: bool = False, + dhcp_service: bool = False, timeout: int = 60, ): """ @@ -2059,6 +2117,8 @@ def create_virtual_network( untagged_ct (bool) - (optional) Create untagged connectivity template for the given virtual-network. + dhcp_service + (bool) - (optimal) Enables DHCP service on virtual network timeout (int) - time (seconds) to wait for creation @@ -2080,12 +2140,15 @@ def create_virtual_network( "vn_id": vn_id, "bound_to": bound_to, "ipv4_enabled": True, - "dhcp_service": "dhcpServiceEnabled", "ipv4_subnet": ipv4_subnet, "ipv4_gateway": ipv4_gateway, } + if dhcp_service: + virt_net['dhcp_service'] = "dhcpServiceEnabled" + if ipv6_enabled: + virt_net["ipv6_enabled"] = True virt_net["ipv6_subnet"] = ipv6_subnet virt_net["ipv6_gateway"] = ipv6_gateway @@ -2287,3 +2350,7 @@ def get_node_relationships( } return self.rest.json_resp_get(url, params=params)['relationships'] + + def get_protocol_sessions(self, bp_id: str): + url = f'/api/blueprints/{bp_id}/protocol-sessions' + return self.rest.json_resp_get(url)['protocol-sessions'] \ No newline at end of file diff --git a/aos/external_systems.py b/aos/external_systems.py index 5279a7b..86e19f8 100644 --- a/aos/external_systems.py +++ b/aos/external_systems.py @@ -77,3 +77,4 @@ def iter_all(self) -> Generator[ExternalRouter, None, None]: def find_by_name(self, rtr_name: str) -> List[ExternalRouter]: return [r for r in self.iter_all() if r.display_name == rtr_name] + diff --git a/tools/ct-template-generator.py b/tools/ct-template-generator.py new file mode 100644 index 0000000..da44110 --- /dev/null +++ b/tools/ct-template-generator.py @@ -0,0 +1,60 @@ +# +# 2023 Per Abildgaard Toft