[docs]defrun(self):"""Run method documentation."""# Create an external-facing network and an iterator for that network.# The iterator will provide the next available netaddr.IPAddress for the given# network.self.external_network=IPNetwork("1.0.0.0/24")external_network_iter=self.external_network.iter_hosts()# Create an internal facing networkinternal_networks=IPNetwork("10.0.0.0/8")# Break the internal network into various subnets# https://netaddr.readthedocs.io/en/latest/tutorial_01.html#supernets-and-subnetsself.internal_subnets=internal_networks.subnet(24)# Create the gateway and firewallfirewall=self.build_front(next(external_network_iter))# Create an internal switchinternal_switch=Vertex(self.g,name="ACME-INTERNAL")internal_switch.decorate(Switch)# Grab a subnet to use for connections to the internal switchinternal_switch_network=next(self.internal_subnets)# Create a generator for the networkinternal_switch_network_iter=internal_switch_network.iter_hosts()# Connect the Firewall to the internal switchfirewall.ospf_connect(internal_switch,next(internal_switch_network_iter),internal_switch_network.netmask,)# Create our first buildingbuilding_1=self.build_building("building1",# The name of the buildingnext(self.internal_subnets),# The building networknum_hosts=3,# The number of hosts for the building)# Connect the first building router to the internal switch.building_1.ospf_connect(internal_switch,next(internal_switch_network_iter),internal_switch_network.netmask,)# Create our second buildingbuilding_2=self.build_building("building2",# The name of the buildingnext(self.internal_subnets),# The building networknum_hosts=3,# The number of hosts for the building)# Connect the second building router to the internal switch.building_2.ospf_connect(internal_switch,next(internal_switch_network_iter),internal_switch_network.netmask,)# Build our data centerself.build_datacenter(building_2,# The building Vertexnext(self.internal_subnets),# Add a network to connect the DC to the buildingnext(self.internal_subnets),# Add a network which is internal to the DC)
[docs]defbuild_front(self,ext_ip):"""Build the ACME infrastructure that is Internet-facing. This method will create the following topology:: switch -- gateway -- switch -- firewall (ACME-EXTERNAL) (GW-FW) Args: ext_ip (netaddr.IPAddress): The external IP address for the gateway (e.g. its Internet facing IP address). Returns: vyos.Helium118: The Firewall object. """# Build the gatewaygateway=Vertex(self.g,"gateway.acme.com")gateway.decorate(Helium118)# Create the external switchext_switch=Vertex(self.g,name="ACME-EXTERNAL")ext_switch.decorate(Switch)# Connect the gateway to the external switchgateway.connect(ext_switch,# The "Internet" facing Switchext_ip,# The external IP address for the gateway (e.g. 1.0.0.1)self.external_network.netmask,# The external subnet mask (e.g. 255.255.255.0))# Build a switch to connect the gateway and firewallgateway_firewall_switch=Vertex(self.g,name="GW-FW")gateway_firewall_switch.decorate(Switch)# Build the firewallfirewall=Vertex(self.g,"firewall.acme.com")firewall.decorate(Helium118)# Create a network and a generator for the network between# the gateway and firewall.gateway_firewall_network=next(self.internal_subnets)gateway_firewall_network_iter=gateway_firewall_network.iter_hosts()# Connect the gateway and the firewall to their respective switches# We will use ``ospf_connect`` to ensure that the OSPF routes are propagated# correctly (as we want to use OSPF as routing protocol inside of the ACME network).gateway.ospf_connect(gateway_firewall_switch,next(gateway_firewall_network_iter),gateway_firewall_network.netmask,)firewall.ospf_connect(gateway_firewall_switch,next(gateway_firewall_network_iter),gateway_firewall_network.netmask,)returnfirewall
[docs]defbuild_building(self,name,network,num_hosts=1):"""Create the building router and hosts. This is a single router with all of the hosts. Assuming that the building is called "building1" the topology will look like:: switch ---- building1 ----- switch ------ hosts (ACME-INTERNAL) (building1-switch) Args: name (str): The name of the building. network (netaddr.IPNetwork): The subnet for the building. num_hosts (int): The number of hosts the building should have. Returns: vyos.Helium118: The building router. """# Create the VyOS router which will connect the building to the ACME network.building=Vertex(self.g,name=f"{name}.acme.com")building.decorate(Helium118)# Create the building-specific switchbuilding_sw=Vertex(self.g,name=f"{name}-switch")building_sw.decorate(Switch)# Create a generator for the building's networkbuilding_network_iter=network.iter_hosts()# Connect the building to the building Switchbuilding.connect(building_sw,next(building_network_iter),network.netmask)# This redistribute routes for directly connected subnets to OSPF peers.# That is, enables these peers to be discoverable by the rest of the OSPF# routing infrastructure.building.redistribute_ospf_connected()# Create the correct number of hostsforiinrange(num_hosts):# Create a new host which is a Ubuntu Desktophost=Vertex(self.g,name=f"{name}-host-{i}.acme.com",# e.g. "building1-host-1.acme.com")host.decorate(Ubuntu2204Desktop)# Connect the host to the building's switchhost.connect(building_sw,# The building switchnext(building_network_iter),# The next available building IP addressnetwork.netmask,# The building's subnet mask)returnbuilding
[docs]defbuild_datacenter(self,building,uplink_network,dc_network):"""Create the data center. This is a single router with all of the servers:: building2 ------ switch ------ datacenter ------ switch ------ servers (building2-DC-switch) (DC-switch) Args: building (vyos.Helium118): The Building router which contains the data center. uplink_network (netaddr.IPNetwork): The network to connect the DC to the building. dc_network (netaddr.IPNetwork): The network for the data center. """# Create a switch to connect the DC with the buildingbuilding_dc_sw=Vertex(self.g,name=f"{building.name}-DC-switch")building_dc_sw.decorate(Switch)# Create the datacenter routerdatacenter=Vertex(self.g,name="datacenter.acme.com")datacenter.decorate(Helium118)# Create a generator for the building's networkuplink_network_iter=uplink_network.iter_hosts()# Connect the building to the building-DC-switchbuilding.ospf_connect(building_dc_sw,next(uplink_network_iter),uplink_network.netmask)# Connect the datacenter to the building-DC-switchdatacenter.ospf_connect(building_dc_sw,next(uplink_network_iter),uplink_network.netmask)# Make the datacenter internal switch and connectdatacenter_sw=Vertex(self.g,name="DC-switch")datacenter_sw.decorate(Switch)# Create a generator for the DC's networkdc_network_iter=dc_network.iter_hosts()# Connect the DC to the internal switchdatacenter.connect(datacenter_sw,next(dc_network_iter),dc_network.netmask)# This redistribute routes for directly connected subnets to OSPF peers.# That is, enables these peers to be discoverable by the rest of the OSPF# routing infrastructure.datacenter.redistribute_ospf_connected()# Make serversforiinrange(3):# Create a new Ubuntu server and add connect it to the DC network switchserver=Vertex(self.g,name=f"datacenter-{i}.acme.com")server.decorate(Ubuntu2204Server)server.connect(datacenter_sw,next(dc_network_iter),dc_network.netmask)