Slice Editor

The subpackage fabrictestbed.slice_editor can be used to specify or design the resources that are needed to be reserved.

Class ExperimentTopology

This class can be used to define an experiment topology. You can instantiate the class into an object, and then use its methods to add nodes and links etc…

<!–

Todo / Note: there’s a typo in the docs that are accessible through python’s help() function. “Define an user topology model”.

–>

from fabrictestbed.slice_editor import ExperimentTopology
t = ExperimentTopology()

Constructor

 
Constructor(self, graph_file: str = None, graph_string: str = None, logger=None)
 
Param graph_file
A file that contains a graph. See the concept of a graph.
Param graph_string
A string that contains a graph. See the concept of a graph.
Param logger
Todo: describe.
t = ExperimentTopology()

Nodes

 
Attribute  nodes
 
Get only
Returns a list of nodes that have been added to the ExperimentTopology.
{Node name:
{‘capacities’: { core: Number of cores, ram: Amount of RAM, disk: Amount of disk space, }.
‘image_ref’: The operating system or the distro of the image.
‘image_type’: ‘qcow2’ Todo: what does this mean?
‘name’: Node name. Todo: the node name is already the key of the object.
‘site’: The site at which the node is deployed.
‘type’: The type of the node. Example: VM is Virtual Machine.}
}
 
Attribute  links
 
Get only
Returns a list of links that have been added to the ExperimentTopology.
{Link Name: {‘layer’: The layer in which the link is. Todo: Where are they defined?, ‘name’: The name given to the link, ‘type’: Todo: what is the type?}[Network interfaces connected to the link]}

Interface List

 
Attribute  interface_list
 
Get only
List all interfaces of the topology as a dictionary. Todo: elaborate more. Does “interfaces” mean “network interfaces”?
({‘capacities’: ‘{ bw: 25G, }’, ‘name’: ‘nic1-p1’, ‘type’: ‘TrunkPort’},
{‘capacities’: ‘{ bw: 25G, }’, ‘name’: ‘nic1-p2’, ‘type’: ‘TrunkPort’})

Add Node

You can use this function to add a node to the topology that you are making.
 
add_node(self, *, name: str, node_id: str = None, site: str, ntype: fim.slivers.network_node.NodeType = VM, **kwargs) -> fim.user.node.Node
 
Param
str
name
A string that names the link.
Param
str
node_id
Todo: what is the ID?
Param site
The site at which you want to create the node. See the concept of sites.
Param ntype
The node type, which is fabrictestbed.slice_editor.NodeType. See NodeType.
Return Node
A Node object. See Node.
t = ExperimentTopology()
n1 = t.add_node(name='n1', site='RENC')
You can use this function to add a link between two nodes in the topology that you are making.
 
add_link(self, *, name: str, node_id: str = None, ltype: fim.slivers.network_link.LinkType = None, interfaces: List[fim.user.interface.Interface], layer: fim.slivers.switch_fabric.SFLayer = None, technology: str = None, **kwargs) -> fim.user.link.Link
 
Param
str
name
A string that names the link.
Param
str
node_id
Todo: what is the ID?
Param ltype
Todo: what are the link types and descriptions?
Param interfaces
A list of the interfaces which this link connects.
Param layer
The layer in which the link should be made. Todo: Where are the layers defined?
Param
str
technology
Todo: What is technology?

Todo: Shouldn’t layout be layout=networkx.drawing.layout.spring_layout)? If so, we need to fix the documentation that we get from python’s help(). It shows “layout=<function fruchterman_reingold_layout at 0x7fd0c264d940></function>”.

ping_link = experiemnt.add_link(

          name='ping_link',
                    
          ltype=LinkType.DAC,
                    
          layer=Layer.L2,
                     
          interfaces=[

               list(filter(

               lambda iff:(iff.name == 'renc1_demo1_nic1'+'-p1'),

               experiemnt.interface_list))[0],

                list(filter(

               lambda iff: (iff.name == 'uky1_demo1_nic1'+'-p1'),

               experiemnt.interface_list))[0]]

)

Draw The Topology

 
Draws the topology specified in the required level of detail.
 
draw(self, *, file_name: str = None, interactive: bool = False, topo_detail: fim.user.topology.TopologyDetail = <TopologyDetail.Derived: 1>, layout=networkx.drawing.layout.spring_layout)
 
Param file_name
Save figure to a file. Drawing type is determined by extension (e.g. “.png”).
Param interactive
Use interactive pyplot mode.
Param topo_detail
Level of detail to use in drawing. Defaults to level 1, which is “Derived”.
Param layout
Use one of available layout algorithms in NetworkX. Defaults to “spring_layout”.
advertised_topology.draw()

Load Topology

 
Load the topology either from a file or from a string.
 
load(self, *, file_name: str = None, graph_string: str = None)
 
Param file_name
The name of the file to load the topology from.
Param graph_string
The string to load the topology from.
t.load(graph_string=gs)
Remove a created link between interfaces by name.
 
remove_link(self, name: str)
 
Param name
The name of the link to remove.
#Todo: add code example.

Remove Node

Remove node by name. All its components, its interfaces and interfaces of components will be removed.
 
remove_node(self, name: str)
 
Param name
The name of the node to be removed.
t.remove_node("n1")

Serialize Topology

Serialize to string or to file, depending on whether file_name is provided.
 
serialize(self, file_name=None) -> str
 
Param file_name
If provided, the graph string is going to be saved to a file. Otherwise, the function is going to return a string.
Return
A string containing GraphML if file_name is None.
slice_graph = t.serialize()

status, reservations = slice_manager.create(

                    slice_name='JupyterSlice2',

                    slice_graph=slice_graph,

                    ssh_key=ssh_key)

Enum NodeType

Enum fabrictestbed.slice_editor.NodeType
 
Server
Todo: elaborate. What is the difference between this and a VM?
VM
A Virtual Machine. A full operating system, virtualized on top of the hypervisor.
Container
A Container. A package of code along with its dependencies that is ready to run on top of any computing environment.
Switch
A data link layer (layer 2) device that can route packets to and from network interfaces connected to it.
NAS
Network-Attached Storage. A data store that provides data to other clients over the network.

Class Node

This class represents nodes in your experiment. When you use the .add_node() function, you get an instance of this class.
And then, you can use the functions of this class to customize the node according to your needs.

Constructor

Don’t call this class on your own.
 
Constructor(self, *, name: str, node_id: str = None, topo: Any, etype: fim.user.model_element.ElementType = , ntype: fim.slivers.network_node.NodeType = None, site: str = None, **kwargs)
 
Todo: even though the user shouldn’t call the constructor on his own, should we still document it? If not, then we should just delete this part.
 

Components

 
Attribute  components
 
Get only
A dictionary of the components that have been added to the node.

Interfaces

 
Attribute  interfaces
 
Get only
A dictionary of the network interfaces that the node has.

Interfaces (list)

 
Attribute  interface_list
 
Get only
A k-Tuple object of the network interfaces that the node has, where k is the number of tuples.

Direct Interfaces

 
Attribute  direct_interfaces
 
Get only
Todo: what is the difference between this and interfaces or interface_list?

Switch Fabrics

 
Attribute  switch_fabrics
 
Get only
The switch fabrics that the node has.

Add Component

Add a component of specified type, model and name to this node. Components can be GPUs, NICs, etc… When working with substrate topologies you must specify the switch_fabric_node_id and provide a list of interface node ids.
 
add_component(self, *, name: str, node_id: str = None, ctype: fim.slivers.attached_components.ComponentType, model: str, switch_fabric_node_id: str = None, interface_node_ids=None, interface_labels=None, **kwargs) -> fim.user.component.Component
 
Param name
A name that you can give to the component, in order to be able to refer to it later.
Param node_id
You can optionally set an ID for the node. If this argument is not provided, and ID will be automatically generated for the node.
Param ctype
The component type, An instance of the enum ComponentType. See ComponentType.
Param model
After specifying the component type, here you can specify what model of that component you want. Todo: list all models of each component type.
Param switch_fabric_node_id
Switch fabric identifier for substrate models. Todo: elaborate.
Param interface_node_ids
Interface identifiers for substrate models. Todo: elaborate.
Param interface_labels
List of labels for interfaces in substrate models. Todo: elaborate.
Return Component
A Component object. Todo: document the Component class and link to it here?
n1 = t.add_node(name='n1', site='RENC')


# Set capacities

cap = Capacities()

cap.set_fields(core=4, ram=4, disk=10)


# Set Properties

n1.set_properties(capacities=cap, image_type='qcow2',
                    image_ref='default_centos_8')


# Add PCI devices

n1.add_component(ctype=ComponentType.SmartNIC,
                    model='ConnectX-5', name='nic1')

Add Switch Fabric

Add a switch fabric to node (mostly needed in substrate topologies). Todo: What’s a “switch fabric” and what are “substrate topologies”?
 
add_switch_fabric(self, *, name: str, node_id: str = None, layer: fim.slivers.switch_fabric.SFLayer)
 
Param name
A string that names the switch fabric.
Param node_id
You can optionally set an ID for the node. If this argument is not provided, and ID will be automatically generated for the node.
Param layer
Layer 1 or 2 or 3. An instance of fabrictestbed.slice_editor.Layer. See the concept of Layers.
Return SwitchFabric
A SwitchFabric object. Todo: document it and link to it?
#Todo: add code example.

Get Component

 
Get a component object by name.
 
get_component(self, name: str)
 
Param name
The name of the component that you want to get.
Return Component
A Component object. Todo: document the Component class and link to it here?
n2 = t2.add_node(name='n2', site='UKY')


#Set properties

n2.set_properties(capacities=cap, image_type='qcow2',

                    image_ref='default_centos_8')


#Add PCI devices

interface2 = n2.add_component(ctype=ComponentType.SmartNIC,

                    model='ConnectX-5', name='nic2')


t2.remove_node("n1")

c1 = n2.get_component("nic2")

Get Property Of Node

Get a property of the Node object.
 
get_property(self, pname: str) -> Any
 
Param pname
The name of the property to be retrieved.
Return Object
The property.

Remove Component

Remove a component from the node (and switch fabrics and their interfaces) by name.
 
remove_component(self, name: str) -> None
 
Param name
The name of the component to be removed.
n2 = t2.add_node(name='n2', site='UKY')


#Set properties

n2.set_properties(capacities=cap, image_type='qcow2',

image_ref='default_centos_8')


#Add PCI devices

interface2 = n2.add_component(ctype=ComponentType.SmartNIC,

                    model='ConnectX-5', name='nic2')

interface2 = n2.add_component(ctype=ComponentType.SmartNIC,

                    model='ConnectX-5', name='nic3')


t2.remove_node("n1")

n2.remove_component("nic2")

Remove Switch Fabric

Remove a switch fabric from the node (and all its interfaces) by name.
 
remove_switch_fabric(self, name: str) -> None
 
Param name
The name of the switch fabric to be removed.
#Todo: Make a code example.

Set Properties Of Node

Set multiple properties of the Node object.
 
set_properties(self, **kwargs)
#Todo: Make a code example.

Set Property Of Node

Set one property of the Node object.
 
set_property(self, pname: str, pval: Any)
Param pname
The name of the property to be set.
Param pval
The value of the property to be set.
#Todo: Make a code example.

Class Capacities

This class can be used to specify the hardware resources that you want to allocate to your slivers. You need to instantiate an object of the class and use set_fields() to specify them. Then you can pass the instatiated object as the “capacities” parameter in the slivers you create.

Constructor

Constructor(self, graph_file: str = None, graph_string: str = None, logger=None)
 
Param graph_file
A file that contains a graph. See the concept of a graph.
Param graph_string
A string that contains a graph. See the concept of a graph.
Param logger
Todo: describe.
cap = Capacities()
cap.set_fields(core=4, ram=4, disk=100)

Todo: do those?
| negative_fields(self) -> List[str]
| returns list of fields that are negative
| :return:
|
| positive_fields(self, fields: List[str]) -> bool
| Return true if indicated fields are positive >0
| :param fields:
| :return:

Set Capacity Fields

Use this to specify the desired resources by setting the parameters of the function to numerical values. Values should be non-negative integers.
 
set_fields(self, **kwargs)
 
cpu
Todo: What is cpu?
core
Number of CPU cores.
ram
Amount of RAM in Gigabytes.
disk
Amount of disk space in Gigabytes.
bw
Amount of Bandwidth in Gbps.
unit
Todo: What are units?
Raises CapacityException
Raised you try to set a non-existent field.
Return self
For call chaining.
cap = Capacities()
cap.set_fields(core=4, ram=4, disk=100)

Set Capacity Fields From JSON.

Set fields from JSON string. If the string is none or empty, nothing happens.
 
from_json(self, json_string: str)
 
Param json_string
The JSON string to set the parameters from. The parameters are the same parameters of the set_fields() function.See set_fields().
Return self
For call chaining.
#Todo: write a code example.

List Fields Of Capacity

 
Returns a sorted list of the fields that were set.
 
list_fields(self)
 
Return
A sorted list of the fields that were set.
print(cap.list_fields())

Capacity To Dictionary

Returns a dictionary of all the fields that have been set. Empty fields are skipped. None is returned if all fields are empty.
 
to_dict(self)
 
Return
A dictionary of all the fields that have been set. Empty fields are skipped. None is returned if all fields are empty.
print(cap.to_dict())

Capacity To JSON

Returns a JSON string of the fields that have been set. Empty string is returnd if there are no values.
 
to_json(self) -> str
 
Return
A JSON string of the fields that have been set. Empty string is returnd if there are no values.
print(cap.to_json())

Enum ComponentType

The ComponentType enum can be used to add components to nodes.

Enum fabrictestbed.slice_manager.Status
GPU
A GPU card.
SmartNIC
A type of network cards (Network Interface Controller) that is more performant than the SharedNIC.
SharedNIC
A type of network cards (Network Interface Controller) that is less performant than the SmartNIC.
FPGA
A programmable integrated circuit.
NVME
A type of persistent storage which is faster than mechanical storage.

Updated on June 2, 2023

Was this article helpful?

Related Articles

Having problems?
Try searching or asking questions in the FABRIC community forums!
Go to Forums

Leave a Comment