def build_slice_with_compute_only(include_components: bool = False, exceed_capacities: bool = False, exceed_components: bool = False, use_hints: bool = False, no_cap: bool = False, instance_type: str = "fabric.c8.m32.d500") -> str: t = fu.ExperimentTopology() n1 = t.add_node(name='n1', site='RENC') n1.set_properties(image_type='qcow2', image_ref='default_centos_8') n2 = t.add_node(name='n2', site='RENC') n2.set_properties(image_type='qcow2', image_ref='default_centos_8') if not no_cap: cap = None if exceed_capacities: cap = fu.Capacities(core=33, ram=64, disk=500) else: cap = fu.Capacities(core=3, ram=61, disk=499) n1.set_properties(capacities=cap) n2.set_properties(capacities=cap) if include_components: n1.add_component(ctype=fu.ComponentType.SmartNIC, model='ConnectX-6', name='nic1') n2.add_component(ctype=fu.ComponentType.NVME, model='P4510', name='c1') n2.add_component(ctype=fu.ComponentType.GPU, model='RTX6000', name='c2') if exceed_components: n2.add_component(ctype=fu.ComponentType.GPU, model='Tesla T4', name='c3') n2.add_component(ctype=fu.ComponentType.SmartNIC, model='ConnectX-6', name='nic1') n2.add_component(ctype=fu.ComponentType.SmartNIC, model='ConnectX-5', name='nic2') if use_hints: cap_hints = fu.CapacityHints(instance_type=instance_type) n1.set_properties(capacity_hints=cap_hints) n2.set_properties(capacity_hints=cap_hints) return t.serialize()
def testSerDes3(self): # multi-format serialization-deserialization test topo = f.ExperimentTopology() topo.add_node(name='n1', site='RENC') cap = f.Capacities(core=1, unit=2) topo.nodes['n1'].capacities = cap topo.nodes['n1'].add_component(ctype=f.ComponentType.SharedNIC, model='ConnectX-6', name='nic1') topo.add_node(name='n2', site='UKY') topo.nodes['n2'].add_component(ctype=f.ComponentType.SharedNIC, model='ConnectX-6', name='nic2') topo.add_network_service(name='s1', nstype=f.ServiceType.L2STS, interfaces=topo.interface_list) slice_graph = topo.serialize(fmt=f.GraphFormat.JSON_NODELINK) print(f'NODE_LINK {slice_graph=}') t1 = f.ExperimentTopology(graph_string=slice_graph) self.assertTrue('n1' in t1.nodes.keys()) self.assertTrue('nic1' in t1.nodes['n1'].components.keys()) cap1 = t1.nodes['n1'].capacities self.assertEqual(cap1.core, 1) self.assertEqual(cap1.unit, 2) print(f'LIST COMPONENTS of n1 {t1.nodes["n1"].components}') print(f'LIST COMPONENTS of n2 {t1.nodes["n2"].components}') self.n4j_imp.delete_all_graphs()
def test_asm_transfer(self): """ Test creating ASM in NetworkX and transition to Neo4j :return: """ t = fu.ExperimentTopology() n1 = t.add_node(name='n1', site='RENC') cap = fu.Capacities(core=4, ram=64, disk=500) n1.set_properties(capacities=cap, image_type='qcow2', image_ref='default_centos_8') n1.add_component(ctype=fu.ComponentType.SmartNIC, model='ConnectX-6', name='nic1') n2 = t.add_node(name='n2', site='RENC') n2.set_properties(capacities=cap, image_type='qcow2', image_ref='default_centos_8') n2.add_component(ctype=fu.ComponentType.GPU, model='RTX6000', name='nic2') slice_graph = t.serialize() #t.serialize(file_name='slice_graph.graphml') generic_graph = self.n4j_imp.import_graph_from_string( graph_string=slice_graph, graph_id=t.graph_model.graph_id) asm_graph = Neo4jASMFactory.create(generic_graph) node_ids = asm_graph.list_all_node_ids() print('ASM Node IDs') print(node_ids) node_id = next(iter(node_ids)) # this is how you map to BQM asm_graph.set_mapping(node_id=node_id, to_graph_id="dead-beef", to_node_id='beef-beef') to_graph, to_node = asm_graph.get_mapping(node_id=node_id) assert (to_graph == "dead-beef") assert (to_node == "beef-beef") # test creating an experiment topology as a cast of an ASM loaded into Neo4j neo4j_topo = fu.ExperimentTopology() neo4j_topo.cast(asm_graph=asm_graph) print(f'New topology on top of {neo4j_topo.graph_model.graph_id}') print(neo4j_topo.nodes) # set allocated capacities or labels # in orchestrator alloc_labels = fu.Labels(instance_parent="worker_node-1") neo4j_topo.nodes['n1'].set_properties(label_allocations=alloc_labels) # in AM provisioned_labels = fu.Labels(instance="open-stack-instance-id-123") neo4j_topo.nodes['n1'].set_properties(labels=provisioned_labels) ri = fu.ReservationInfo(reservation_id="01234", reservation_state='READY') neo4j_topo.nodes['n1'].set_properties(reservation_info=ri) self.n4j_imp.delete_all_graphs()
def testSerDes2(self): # more thorough serialization-deserialization test topo = f.ExperimentTopology() topo.add_node(name='n1', site='RENC') cap = f.Capacities(core=1, unit=2) topo.nodes['n1'].capacities = cap topo.nodes['n1'].add_component(ctype=f.ComponentType.SharedNIC, model='ConnectX-6', name='nic1') topo.add_node(name='n2', site='UKY') topo.nodes['n2'].add_component(ctype=f.ComponentType.SharedNIC, model='ConnectX-6', name='nic2') topo.add_network_service(name='s1', nstype=f.ServiceType.L2STS, interfaces=topo.interface_list) slice_graph = topo.serialize() print('\n\n\nINITIAL TOPO') print(topo) # Import it in the neo4j as ASM generic_graph = self.n4j_imp.import_graph_from_string( graph_string=slice_graph) asm_graph = Neo4jASMFactory.create(generic_graph) # Serialize ASM orch_graph = asm_graph.serialize_graph() # Reload Experiment topology from serialized ASM t1 = f.ExperimentTopology(graph_string=orch_graph) print('\n\n\nRELOADED TOPO') print(t1) self.assertTrue('n1' in t1.nodes.keys()) self.assertTrue('nic1' in t1.nodes['n1'].components.keys()) cap1 = t1.nodes['n1'].capacities self.assertEqual(cap1.core, 1) self.assertEqual(cap1.unit, 2) print(f'LIST COMPONENTS of n1 {t1.nodes["n1"].components}') print(f'LIST COMPONENTS of n2 {t1.nodes["n2"].components}') self.n4j_imp.delete_all_graphs()
def build_2_site_ptp_slice_sriov() -> str: """ 2-site for PTP service between two shared card ports """ t = fu.ExperimentTopology() n1 = t.add_node(name='n1', site='RENC', ntype=fu.NodeType.VM) n2 = t.add_node(name='n2', site='UKY') cap = fu.Capacities(core=2, ram=8, disk=100) n1.set_properties(capacities=cap, image_type='qcow2', image_ref='default_centos_8') n2.set_properties(capacities=cap, image_type='qcow2', image_ref='default_centos_8') n1.add_component(model_type=fu.ComponentModelType.SharedNIC_ConnectX_6, name='n1-nic1') n2.add_component(model_type=fu.ComponentModelType.SharedNIC_ConnectX_6, name='n2-nic1') n2.add_component(ctype=fu.ComponentType.NVME, model='P4510', name='c1') t.add_network_service(name='ptp1', nstype=fu.ServiceType.L2PTP, interfaces=[n1.interface_list[0], n2.interface_list[0]]) return t.serialize()
def build_slice() -> str: t = fu.ExperimentTopology() n1 = t.add_node(name='n1', site='RENC', ntype=fu.NodeType.VM) n2 = t.add_node(name='n2', site='RENC') n3 = t.add_node(name='n3', site='RENC') cap = fu.Capacities(core=2, ram=8, disk=100) n1.set_properties(capacities=cap, image_type='qcow2', image_ref='default_centos_8') n2.set_properties(capacities=cap, image_type='qcow2', image_ref='default_centos_8') n3.set_properties(capacities=cap, image_type='qcow2', image_ref='default_centos_8') n1.add_component(model_type=fu.ComponentModelType.SharedNIC_ConnectX_6, name='n1-nic1') n2.add_component(model_type=fu.ComponentModelType.SmartNIC_ConnectX_6, name='n2-nic1') n2.add_component(ctype=fu.ComponentType.NVME, model='P4510', name='c1') n3.add_component(model_type=fu.ComponentModelType.SmartNIC_ConnectX_5, name='n3-nic1') t.add_network_service(name='bridge1', nstype=fu.ServiceType.L2Bridge, interfaces=t.interface_list) return t.serialize()
def testNodeAndServiceSlivers(self): t = f.ExperimentTopology() t.add_node(name='n1', site='RENC') t.nodes['n1'].capacities = f.Capacities(core=1) t.nodes['n1'].add_component(name='c1', ctype=f.ComponentType.SmartNIC, model='ConnectX-6') d = ABCPropertyGraph.sliver_to_dict(t.nodes['n1'].get_sliver()) t.add_node(name='n2', site='RENC') t.nodes['n2'].add_component(name='c2', ctype=f.ComponentType.SmartNIC, model='ConnectX-6') t.nodes['n2'].add_component(name='c3', ctype=f.ComponentType.NVME, model='P4510') t.add_network_service(name='s1', nstype=f.ServiceType.L2Bridge, interfaces=t.interface_list) jns = JSONSliver.sliver_to_json(t.nodes['n1'].get_sliver()) ns1 = JSONSliver.node_sliver_from_json(jns) jns = JSONSliver.sliver_to_json(t.nodes['n2'].get_sliver()) ns2 = JSONSliver.node_sliver_from_json(jns) ness = JSONSliver.sliver_to_json(t.network_services['s1'].get_sliver()) nss1 = JSONSliver.network_service_sliver_from_json(ness) self.assertEqual(ns1.capacities.core, 1) self.assertEqual(len(ns1.attached_components_info.list_devices()), 1) self.assertEqual(len(ns2.attached_components_info.list_devices()), 2) self.assertEqual(len(nss1.interface_info.list_interfaces()), 4) inames = [ i.resource_name for i in nss1.interface_info.list_interfaces() ] self.assertTrue('n2-c2-p1' in inames) self.assertEqual( ns1.attached_components_info.list_devices() [0].network_service_info.list_services() [0].interface_info.list_interfaces()[0].capacities.bw, 100)
def testNetworkServices(self): n1 = self.topo.add_node(name='Node1', site='RENC') n2 = self.topo.add_node(name='Node2', site='UKY', ntype=f.NodeType.Server) n3 = self.topo.add_node(name='Node3', site='RENC', management_ip='123.45.67.98', image_ref='http://some.image', image_type='image type') # component checks n1.add_component(ctype=f.ComponentType.GPU, model='RTX6000', name='gpu1') n1.add_component(model_type=f.ComponentModelType.SharedNIC_ConnectX_6, name='nic1') n1.add_component(model_type=f.ComponentModelType.SmartNIC_ConnectX_6, name='nic4') n2.add_component(ctype=f.ComponentType.SmartNIC, model='ConnectX-6', name='nic2') nc3 = n3.add_component(ctype=f.ComponentType.SharedNIC, model='ConnectX-6', name='nic3', boot_script='#!/bin/bash echo *') #tags on model elements (nodes, links, components, interfaces, network services) n1.tags = f.Tags('blue', 'heavy') self.assertTrue('blue' in n1.tags) # unset the tags n1.tags = None self.assertEqual(n1.tags, None) # flags on model elements n1.flags = f.Flags(auto_config=True) self.assertTrue(n1.flags.auto_config) n1.flags = None self.assertEqual(n1.flags, None) self.assertEqual(nc3.boot_script, '#!/bin/bash echo *') #boot script on nodes only n1.boot_script = """ #!/bin/bash echo * """ self.assertTrue("bash" in n1.boot_script) n1.boot_script = None self.assertIsNone(n1.boot_script) # measurement data on model elements (nodes, links, components, interfaces, network services) # can be set simply as json string (string length not to exceed 1M) n1.mf_data = json.dumps( {'k1': ['some', 'measurement', 'configuration']}) # you are guaranteed that whatever is on mf_data is JSON parsable and can be reconstituted into # an object mf_object1 = n1.mf_data self.assertTrue( mf_object1['k1'] == ['some', 'measurement', 'configuration']) # when nothing is set, it is None self.assertEqual(n2.mf_data, None) # you can also set it as MeasurementData object my_meas_data_object = {'key1': {'key2': ['v1', 2]}} n1.mf_data = f.MeasurementData(json.dumps(my_meas_data_object)) # you can also just pass a JSON serializable object to MeasurementData constructor: n1.mf_data = f.MeasurementData(my_meas_data_object) # or even an serializable object itself. Either way the limit of 1M on the JSON string # length is enforced n1.mf_data = my_meas_data_object # for most uses, just set the object my_meas_data_object = {'key1': {'key2': ['some', 'config', 'info']}} n1.mf_data = my_meas_data_object # you get back your object (in this case a dict) self.assertTrue(isinstance(n1.mf_data, dict)) mf_object2 = n1.mf_data self.assertTrue( mf_object2['key1'] == {'key2': ['some', 'config', 'info']}) class MyClass: def __init__(self, val): self.val = val # this is not a valid object - json.dumps() will fail on it bad_meas_data_object = {'key1': MyClass(3)} with self.assertRaises(MeasurementDataError): n1.mf_data = bad_meas_data_object # also cannot use bad strings with self.assertRaises(MeasurementDataError): # you cannot assign non-json string to measurement data either as MeasurementData object n1.mf_data = f.MeasurementData("not parsable json") with self.assertRaises(MeasurementDataError): # or directly as string n1.mf_data = 'random string' # most settable properties can be unset by setting them to None (there are exceptions, like e.g. name) n1.mf_data = None self.assertIsNone(n1.mf_data) gpu1 = n1.components['gpu1'] nic1 = n1.components['nic1'] nic2 = n2.components['nic2'] p1 = nic2.interfaces['nic2-p1'] p2 = nic2.interfaces['nic2-p2'] cap = f.Capacities(bw=50, unit=1) nic1.capacities = cap lab = f.Labels(ipv4="192.168.1.12") nic1.labels = lab caphints = f.CapacityHints(instance_type='blah') n1.capacity_hints = caphints # check capacities, hints labels on the graph n1p = self.topo.nodes['Node1'] caphints1 = n1p.get_property('capacity_hints') assert (caphints.instance_type == caphints1.instance_type) caphints1 = n1p.capacity_hints assert (caphints.instance_type == caphints1.instance_type) #s1 = self.topo.add_network_service(name='s1', nstype=f.ServiceType.L2Bridge, interfaces=self.topo.interface_list) s1 = self.topo.add_network_service(name='s1', nstype=f.ServiceType.L2STS, interfaces=[ n1.interface_list[0], n2.interface_list[0], n3.interface_list[0] ]) # facilities fac1 = self.topo.add_facility(name='RENCI-DTN', site='RENC', capacities=f.Capacities(bw=10), labels=f.Labels(vlan='100')) # facility needs to be connected via a service to something else sfac = self.topo.add_network_service( name='s-fac', nstype=f.ServiceType.L2STS, interfaces=[fac1.interface_list[0], n1.interface_list[2]]) self.assertEqual(s1.layer, f.Layer.L2) print(fac1.network_services['RENCI-DTN-ns'].labels) self.assertEqual(fac1.network_services['RENCI-DTN-ns'].layer, f.Layer.L2) self.assertEqual(fac1.interface_list[0].labels.vlan, '100') # this is typically done by orchestrator s1.gateway = Gateway( Labels(ipv4_subnet="192.168.1.0/24", ipv4="192.168.1.1", mac="00:11:22:33:44:55")) self.assertEqual(s1.gateway.gateway, "192.168.1.1") self.assertEqual(s1.gateway.subnet, "192.168.1.0/24") print(f'S1 has these interfaces: {s1.interface_list}') self.assertEqual(len(s1.interface_list), 3) self.topo.validate() # Import it in the neo4j as ASM slice_graph = self.topo.serialize() generic_graph = self.n4j_imp.import_graph_from_string( graph_string=slice_graph) asm_graph = Neo4jASMFactory.create(generic_graph) asm_graph.validate_graph() self.n4j_imp.delete_all_graphs() s1p = self.topo.network_services['s1'] print(f'S1 has these interfaces: {s1p.interface_list}') s1.disconnect_interface(interface=p1) print(f'S1 has these interfaces: {s1.interface_list}') self.assertEqual(len(s1.interface_list), 2) # validate the topology self.topo.validate() # Import it in the neo4j as ASM generic_graph = self.n4j_imp.import_graph_from_string( graph_string=slice_graph) asm_graph = Neo4jASMFactory.create(generic_graph) asm_graph.validate_graph() self.n4j_imp.delete_all_graphs() self.topo.remove_network_service('s1') with self.assertRaises(TopologyException): # connection conflict because we have an interface connecting to s-fac s2 = self.topo.add_network_service( name='s2', nstype=f.ServiceType.L2PTP, interfaces=self.topo.interface_list) s2 = self.topo.add_network_service( name='s2', nstype=f.ServiceType.L2PTP, interfaces=[n1.interface_list[1], n2.interface_list[1]]) self.assertEqual(len(s2.interface_list), 2) print(f'S2 has these interfaces: {s2.interface_list}') print(f'There are {self.topo.links} links left in topology') self.assertEqual(len(self.topo.links), 4) print( f'There are {self.topo.network_services} Network services in topology' ) self.assertEqual(len(self.topo.network_services), 7) self.topo.validate() self.topo.remove_network_service('s2') self.topo.validate() self.assertEqual(len(self.topo.network_services), 6) n1.remove_component('nic1') self.assertEqual(len(self.topo.network_services), 5)