Source code for pyNTM.demand

"""A Demand is a traffic load that traverses the network from a source Node
to a destination Node"""


[docs]class Demand(object): """ A representation of traffic load on the modeled network """ def __init__(self, source_node_object, dest_node_object, traffic=0, name="none"): self.source_node_object = source_node_object self.dest_node_object = dest_node_object self.traffic = traffic self.name = name self.path = "Unrouted" self._path_detail = "Unrouted_detail" # Validate traffic value if not (isinstance(traffic, (int, float))) or traffic < 0: raise ValueError("Must be a positive int or float") @property def _key(self): """Unique identifier for the demand: (Node('source').name, Node('dest').name, name)""" return (self.source_node_object.name, self.dest_node_object.name, self.name) def __repr__(self): return "Demand(source = %s, dest = %s, traffic = %s, name = %r)" % ( self.source_node_object.name, self.dest_node_object.name, self.traffic, self.name, ) @property def path_detail(self): """ Returns a detailed breakdown of the Demand path. Each path will have the following information: items: The combination of Interfaces and/or LSPs that the Demand takes from source to destination splits: each item on the path (Interface and/or LSP) and the number of cumulative ECMP path splits that the Demand has transited as it egresses the source node for that element. Splits can be used to calculate how much of the Demand's traffic is on a certain path (see path_traffic below) or how much of the Demand's traffic is on a certain element. The demand object's ``path_detail`` property can be very useful to determine how much of the demand's traffic egresses each object (interface, LSP) in the path. For example, sample demand ``Demand(source = A, dest = E, traffic = 24, name = 'dmd_a_e_1')`` has 24 units of traffic. Here is the ``path_0`` entry for the sample demand:: 'path_0': { 'items': [Interface(name = 'A-to-B', cost = 4, capacity = 100, node_object = Node('A'), remote_node_object = Node('B'), circuit_id = '1'), Interface(name = 'B-to-E_3', cost = 3, capacity = 200, node_object = Node('B'), remote_node_object = Node('E'), circuit_id = '27') ], 'path_traffic': 4.0, 'splits': {Interface(name = 'A-to-B', cost = 4, capacity = 100, node_object = Node('A'), remote_node_object = Node('B'), circuit_id = '1'): 2, Interface(name = 'B-to-E_3', cost = 3, capacity = 200, node_object = Node('B'), remote_node_object = Node('E'), circuit_id = '27'): 6} } The ``path_0`` component of the ``path_detail`` property in this example shows the following: * ``Interface(name = 'A-to-B', cost = 4, capacity = 100, node_object = Node('A'), remote_node_object = Node('B'), circuit_id = '1')`` has **2** splits * ``Interface(name = 'B-to-E_3', cost = 3, capacity = 200, node_object = Node('B'), remote_node_object = Node('E'), circuit_id = '27')`` has **6** splits To get the amount of traffic load from the specific demand that transits each interface, divide the amount of traffic that the demand has by the number of splits for the object: * ``Interface(name = 'A-to-B', cost = 4, capacity = 100, node_object = Node('A'), remote_node_object = Node('B'), circuit_id = '1')`` carries **24 / 2 = 12** units of traffic from the sample demand. * ``Interface(name = 'B-to-E_3', cost = 3, capacity = 200, node_object = Node('B'), remote_node_object = Node('E'), circuit_id = '27')`` carries **24 / 6 = 4** units of traffic from the sample demand. Since the minimum amount of traffic found on any object in ``path_0`` is 4 units of traffic, ``path_traffic`` for ``path_0`` = 4. :return: Dict of path entries (keys). The value for each key is another dict with 3 keys: 'items', 'splits', and 'path_traffic'. Each is described above. # noqa E501 """ return self._path_detail