aboutsummaryrefslogtreecommitdiffstats
path: root/vicn/core/address_mgr.py
diff options
context:
space:
mode:
Diffstat (limited to 'vicn/core/address_mgr.py')
-rw-r--r--vicn/core/address_mgr.py181
1 files changed, 181 insertions, 0 deletions
diff --git a/vicn/core/address_mgr.py b/vicn/core/address_mgr.py
new file mode 100644
index 00000000..7df5e4ac
--- /dev/null
+++ b/vicn/core/address_mgr.py
@@ -0,0 +1,181 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2017 Cisco and/or its affiliates.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import ipaddress
+import logging
+import random
+import struct
+import socket
+
+from netmodel.util.deprecated import deprecated
+from netmodel.util.singleton import Singleton
+from netmodel.util.toposort import toposort, toposort_flatten
+
+log = logging.getLogger(__name__)
+
+#------------------------------------------------------------------------------
+# SharedResource
+#------------------------------------------------------------------------------
+
+class SharedResource:
+ """
+ Base class for allocating shared resource
+ """
+ def __init__(self):
+ self._counter = 0
+ self._values = dict()
+
+ def __next__(self):
+ ret = self._counter
+ self._counter += 1
+ return ret
+
+ def get(self, requestor, tag = None):
+ if requestor not in self._values:
+ self._values[requestor] = dict()
+ if tag not in self._values[requestor]:
+ self._values[requestor][tag] = next(self)
+ return self._values[requestor][tag]
+
+#------------------------------------------------------------------------------
+
+class Vlan(SharedResource):
+ """
+ SharedResource: Vlan
+
+ Manages VLAN allocation
+ """
+
+ def get(self, requestor, tag = None):
+ if requestor not in self._values:
+ self._values[requestor] = dict()
+ if tag not in self._values[requestor]:
+ self._values[requestor][tag] = (next(self)+1)
+ return self._values[requestor][tag]
+
+#------------------------------------------------------------------------------
+
+MAX_DEVICE_NAME_SIZE = 15
+
+class DeviceName(SharedResource):
+
+ def get(self, *args, prefix = None, **kwargs):
+ count = super().get(*args, **kwargs)
+ device_name = '{}{}'.format(prefix, count)
+ if len(device_name) > MAX_DEVICE_NAME_SIZE:
+ overflow = len(device_name) - MAX_DEVICE_NAME_SIZE
+ max_prefix_len = len(prefix) - overflow
+ device_name = '{}{}'.format(prefix[:max_prefix_len], count)
+ return device_name
+
+#------------------------------------------------------------------------------
+
+class IpAddress(SharedResource):
+ pass
+
+class Ipv4Address(IpAddress):
+ pass
+
+class Ipv6Address(IpAddress):
+ pass
+
+#------------------------------------------------------------------------------
+# AddressManager
+#------------------------------------------------------------------------------
+
+class AddressManager(metaclass = Singleton):
+ """
+ The purpose of this class is to generate sequential deterministic MAC/IP
+ addresses in order to assign them to the node in the network.
+ """
+
+ MAP_TYPE = {
+ 'vlan': Vlan,
+ 'device_name': DeviceName,
+ }
+
+ def __init__(self):
+ self._ips = dict()
+ self._macs = dict()
+
+ self._pools = dict()
+
+ from vicn.core.resource_mgr import ResourceManager
+
+ network = ResourceManager().get('network')
+ network = ipaddress.ip_network(network, strict=False)
+ self._next_ip = network[1]
+
+ mac_address_base = ResourceManager().get('mac_address_base')
+ self._next_mac = int(mac_address_base, 0) + 1
+
+ def get(self, resource_type, requestor, *args, tag=None, scope=None,
+ **kwargs):
+ """
+ Params:
+ type : the type of shared resource to be requested
+ requestor: name of the resource that requests the shared resource, in
+ order to reattribute the same if requested multiple times.
+ tag: use when a single resource request multiple times the same
+ resource.
+ scope: None = global scope by default. Ensure uniqueness of resource
+ at global scope
+ """
+ if not scope in self._pools:
+ self._pools[scope] = dict()
+ if not resource_type in self._pools[scope]:
+ self._pools[scope][resource_type] = self.MAP_TYPE[resource_type]()
+ return self._pools[scope][resource_type].get(requestor, tag,
+ *args, **kwargs)
+
+ #--------------------------------------------------------------------------
+ # Attributes
+ #--------------------------------------------------------------------------
+
+ def get_mac(self, resource_name):
+ """
+ Generate a new mac address to assign to the containers created.
+
+ :return: The MAC address
+ """
+
+ if resource_name in self._macs:
+ return self._macs[resource_name]
+
+ mac = ':'.join(map(''.join,
+ zip(*[iter(hex(self._next_mac)[2:].zfill(12))]*2)))
+ self._next_mac += 1
+
+ self._macs[resource_name] = mac
+ return mac
+
+ def get_ip(self, resource):
+ """
+ Generate a new ip address to assign to the containers created.
+
+ :return: The IP address
+ """
+
+ if resource in self._ips:
+ return self._ips[resource]
+
+ ip = str(self._next_ip)
+ self._next_ip += 1
+
+ self._ips[resource] = ip
+ return ip