aboutsummaryrefslogtreecommitdiffstats
path: root/vicn/resource
diff options
context:
space:
mode:
authorMarcel Enguehard <mengueha+fdio@cisco.com>2017-05-29 13:13:32 +0200
committerMarcel Enguehard <mengueha+fdio@cisco.com>2017-05-29 13:13:32 +0200
commita836e5c16ea7df38646c46f2e9ffc6163ab05f06 (patch)
treed5cf3b799af7e9a328db245647a5cdce0ba744f4 /vicn/resource
parentbe0b435d307173598c30fcacc421b17112137099 (diff)
Misc bug fixes
*IP assignment *Node is a key attribute *Up-to-date packages *Trailing whitespaces ... Change-Id: Id8e2a5f7b2c4506f326b3c4bc991fa65f53fca5c Signed-off-by: Marcel Enguehard <mengueha+fdio@cisco.com>
Diffstat (limited to 'vicn/resource')
-rw-r--r--vicn/resource/application.py1
-rw-r--r--vicn/resource/central.py32
-rw-r--r--vicn/resource/icn/forwarder.py10
-rw-r--r--vicn/resource/icn/icn_application.py8
-rw-r--r--vicn/resource/interface.py3
-rw-r--r--vicn/resource/ip/prefix_tree.py86
-rw-r--r--vicn/resource/ip_assignment.py38
-rw-r--r--vicn/resource/linux/file.py9
-rw-r--r--vicn/resource/linux/keypair.py12
-rw-r--r--vicn/resource/linux/link.py3
-rw-r--r--vicn/resource/linux/net_device.py1
-rw-r--r--vicn/resource/linux/package_manager.py3
-rw-r--r--vicn/resource/linux/physical.py2
-rw-r--r--vicn/resource/lxd/lxc_container.py26
-rw-r--r--vicn/resource/lxd/lxc_image.py20
-rw-r--r--vicn/resource/vpp/cicn.py18
-rw-r--r--vicn/resource/vpp/dpdk_device.py6
-rw-r--r--vicn/resource/vpp/vpp.py16
-rw-r--r--vicn/resource/vpp/vpp_host.py10
19 files changed, 163 insertions, 141 deletions
diff --git a/vicn/resource/application.py b/vicn/resource/application.py
index f5341f2b..0f245496 100644
--- a/vicn/resource/application.py
+++ b/vicn/resource/application.py
@@ -26,4 +26,5 @@ class Application(Resource):
mandatory = True,
multiplicity = Multiplicity.ManyToOne,
reverse_name = 'applications',
+ key = True,
reverse_description = 'Applications installed on node')
diff --git a/vicn/resource/central.py b/vicn/resource/central.py
index 09b24184..4398ae5a 100644
--- a/vicn/resource/central.py
+++ b/vicn/resource/central.py
@@ -20,7 +20,7 @@ import logging
import networkx as nx
import os
-from netmodel.model.type import String
+from netmodel.model.type import String, Integer
from netmodel.util.misc import pairwise
from vicn.core.attribute import Attribute, Reference
from vicn.core.exception import ResourceNotFound
@@ -219,6 +219,9 @@ class IPRoutes(Resource):
"""
routing_strategy = Attribute(String)
+ def __after__(self):
+ return ("IpAssignment",)
+
#--------------------------------------------------------------------------
# Resource lifecycle
#--------------------------------------------------------------------------
@@ -246,17 +249,16 @@ class IPRoutes(Resource):
def _get_ip_origins(self):
origins = dict()
for group in self.groups:
- for node in group.iter_by_type_str('node'):
- node_uuid = node._state.uuid
- if not node_uuid in origins:
- origins[node_uuid] = list()
- for interface in node.interfaces:
- # XXX temp fix (WouldBlock)
- try:
- origins[node_uuid].append(interface.ip4_address)
- if interface.ip6_address: #Control interfaces have no v6 address
- origins[node_uuid].append(interface.ip6_address)
- except: pass
+ for channel in group.iter_by_type_str('channel'):
+ for interface in channel.interfaces:
+ node_uuid = interface.node._state.uuid
+ if not node_uuid in origins:
+ origins[node_uuid] = list()
+ ip4 = interface.ip4_address
+ origins[node_uuid].append(interface.ip4_address)
+ if interface.ip6_address:
+ ip6 = interface.ip6_address
+ origins[node_uuid].append(interface.ip6_address)
return origins
def _get_ip_routes(self):
@@ -595,6 +597,9 @@ class CentralIP(Resource):
mandatory = True)
ip4_data_prefix = Attribute(String, description="Prefix for IPv4 forwarding",
mandatory = True)
+ ip6_max_link_prefix = Attribute(Integer,
+ description = 'Maximum prefix size assigned to each link',
+ default = 64)
#--------------------------------------------------------------------------
# Resource lifecycle
@@ -610,7 +615,8 @@ class CentralIP(Resource):
ip4_assign = Ipv4Assignment(prefix = self.ip4_data_prefix,
groups = Reference(self, 'groups'))
ip6_assign = Ipv6Assignment(prefix = self.ip6_data_prefix,
- groups = Reference(self, 'groups'))
+ groups = Reference(self, 'groups'),
+ max_prefix_size = self.ip6_max_link_prefix)
ip_routes = IPRoutes(owner = self,
groups = Reference(self, 'groups'),
routing_strategy = self.ip_routing_strategy)
diff --git a/vicn/resource/icn/forwarder.py b/vicn/resource/icn/forwarder.py
index a719caf7..748532cf 100644
--- a/vicn/resource/icn/forwarder.py
+++ b/vicn/resource/icn/forwarder.py
@@ -40,19 +40,17 @@ class Forwarder(ICNApplication, ABC):
faces = Attribute(Face, description = 'ICN ffaces of the forwarder',
multiplicity = Multiplicity.OneToMany,
reverse_name = 'forwarder')
- routes = Attribute(Route, description = 'Routes in the ICN FIB',
+ routes = Attribute(Route, description = 'Routes in the ICN FIB',
multiplicity = Multiplicity.OneToMany,
reverse_name = 'forwarder')
- cache_size = Attribute(Integer,
+ cache_size = Attribute(Integer,
description = 'Size of the cache (in chunks)',
default = DEFAULT_CACHE_SIZE)
- cache_policy = Attribute(String, description = 'Cache policy',
+ cache_policy = Attribute(String, description = 'Cache policy',
default = DEFAULT_CACHE_POLICY)
- strategy = Attribute(String, description = 'Forwarding Strategy',
+ strategy = Attribute(String, description = 'Forwarding Strategy',
default = DEFAULT_STRATEGY)
config_file = Attribute(String, description = 'Configuration file')
- port = Attribute(Integer, description = 'Default listening port',
- default = lambda self: self._get_default_port())
log_file = Attribute(String, description = 'Log file')
# Overloaded attributes
diff --git a/vicn/resource/icn/icn_application.py b/vicn/resource/icn/icn_application.py
index 5abee3c5..817d9403 100644
--- a/vicn/resource/icn/icn_application.py
+++ b/vicn/resource/icn/icn_application.py
@@ -16,19 +16,19 @@
# limitations under the License.
#
-from vicn.resource.linux.application import LinuxApplication
+from vicn.resource.linux.application import LinuxApplication
from vicn.core.attribute import Attribute
from netmodel.model.type import Integer
-ICN_SUITE_CCNX_1_0=0
-ICN_SUITE_NDN=1
+ICN_SUITE_CCNX_1_0=1
+ICN_SUITE_NDN=2
class ICNApplication(LinuxApplication):
"""
Resource: ICNApplication
"""
- protocol_suites = Attribute(Integer,
+ protocol_suites = Attribute(Integer,
description = 'Protocol suites supported by the application',
default = lambda self: self._def_protocol_suite())
diff --git a/vicn/resource/interface.py b/vicn/resource/interface.py
index db5f5427..0ae2dc94 100644
--- a/vicn/resource/interface.py
+++ b/vicn/resource/interface.py
@@ -30,7 +30,8 @@ class Interface(Resource):
node = Attribute(Node, description = 'Node to which the interface belongs',
multiplicity = Multiplicity.ManyToOne,
reverse_name = 'interfaces',
- mandatory = True)
+ mandatory = True,
+ key = True)
channel = Attribute(Channel, description = 'Channel to which the interface is attached',
multiplicity = Multiplicity.ManyToOne,
reverse_name = 'interfaces')
diff --git a/vicn/resource/ip/prefix_tree.py b/vicn/resource/ip/prefix_tree.py
index d3a8139a..f5f7d1e9 100644
--- a/vicn/resource/ip/prefix_tree.py
+++ b/vicn/resource/ip/prefix_tree.py
@@ -20,8 +20,9 @@ from socket import inet_pton, inet_ntop, AF_INET6
from struct import unpack, pack
from abc import ABCMeta
-class NotEnoughAddresses(Exception):
- pass
+class PrefixTreeException(Exception): pass
+class NotEnoughAddresses(PrefixTreeException): pass
+class UnassignablePrefix(PrefixTreeException): pass
class Prefix(metaclass=ABCMeta):
@@ -33,7 +34,6 @@ class Prefix(metaclass=ABCMeta):
ip_address = self.aton(ip_address)
self.ip_address = ip_address
self.prefix_size = prefix_size
- self._range = self.limits()
def __contains__(self, obj):
#it can be an IP as a integer
@@ -50,6 +50,14 @@ class Prefix(metaclass=ABCMeta):
return self._contains_prefix(obj)
+ @classmethod
+ def mask(cls):
+ mask_len = cls.MAX_PREFIX_SIZE//8 #Converts from bits to bytes
+ mask = 0
+ for step in range(0,mask_len):
+ mask = (mask << 8) | 0xff
+ return mask
+
def _contains_prefix(self, prefix):
assert isinstance(prefix, type(self))
return (prefix.prefix_size >= self.prefix_size and
@@ -58,10 +66,10 @@ class Prefix(metaclass=ABCMeta):
#Returns the first address of a prefix
def first_prefix_address(self):
- return self.ip_address & (self.MASK << (self.MAX_PREFIX_SIZE-self.prefix_size))
+ return self.ip_address & (self.mask() << (self.MAX_PREFIX_SIZE-self.prefix_size))
def last_prefix_address(self):
- return self.ip_address | (self.MASK >> self.prefix_size)
+ return self.ip_address | (self.mask() >> self.prefix_size)
def limits(self):
return self.first_prefix_address(), self.last_prefix_address()
@@ -77,12 +85,20 @@ class Prefix(metaclass=ABCMeta):
return hash(str(self))
def __iter__(self):
- for i in range(self._range[0], self._range[1]+1):
+ for i in range(self.first_prefix_address(), self.last_prefix_address()+1):
yield self.ntoa(i)
+ #Iterates by steps of prefix_size, e.g., on all available /31 in a /24
+ def get_iterator(self, prefix_size=None):
+ if prefix_size is None:
+ prefix_size=self.MAX_PREFIX_SIZE
+ assert (prefix_size >= self.prefix_size and prefix_size<=self.MAX_PREFIX_SIZE)
+ step = 2**(self.MAX_PREFIX_SIZE - prefix_size)
+ for ip in range(self.first_prefix_address(), self.last_prefix_address()+1, step):
+ yield type(self)(ip, prefix_size)
+
class Inet4Prefix(Prefix):
- MASK = 0xffffffff
MAX_PREFIX_SIZE = 32
@classmethod
@@ -103,50 +119,48 @@ class Inet4Prefix(Prefix):
class Inet6Prefix(Prefix):
- MASK = 0xffffffffffffffff
- MAX_PREFIX_SIZE = 64
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self._range = self.limits(True)
+ MAX_PREFIX_SIZE = 128
@classmethod
- def aton (cls, address, with_suffix=False):
- ret, suffix = unpack(">QQ", inet_pton(AF_INET6, address))
- if with_suffix:
- ret = (ret << 64) | suffix
- return ret
+ def aton (cls, address):
+ prefix, suffix = unpack(">QQ", inet_pton(AF_INET6, address))
+ return (prefix << 64) | suffix
@classmethod
- def ntoa (cls, address, with_suffix=False):
- ret = None
- if with_suffix:
- ret = inet_ntop(AF_INET6, pack(">QQ", address >> 64, address & ((1 << 64) -1)))
- else:
- ret = inet_ntop(AF_INET6, pack(">QQ", address, 0))
- return ret
-
- def limits(self, with_suffix=False):
- ret = super().limits()
- if with_suffix:
- ret = ret[0] << 64, ret[1] << 64 | self.MASK
- return ret
-
- def __iter__(self):
- for i in range(*self._range):
- yield self.ntoa(i, True)
+ def ntoa (cls, address):
+ return inet_ntop(AF_INET6, pack(">QQ", address >> 64, address & ((1 << 64) -1)))
+
+ #skip_internet_address: skip a:b::0, as v6 often use default /64 prefixes
+ def get_iterator(self, prefix_size=None, skip_internet_address=None):
+ if skip_internet_address is None:
+ #We skip the internet address if we iterate over Addresses
+ if prefix_size is None:
+ skip_internet_address = True
+ #But not if we iterate over prefixes
+ else:
+ skip_internet_address = False
+ it = super().get_iterator(prefix_size)
+ if skip_internet_address:
+ next(it)
+ return it
###### PREFIX TREE ######
class PrefixTree:
- def __init__(self, prefix):
+
+ #Use max_served_prefix to set a maximum served prefix size (e.g., /64 for IPv6)
+ def __init__(self, prefix, max_served_prefix=None):
self.prefix = prefix
self.prefix_cls = type(prefix)
+ if max_served_prefix is None:
+ max_served_prefix = self.prefix_cls.MAX_PREFIX_SIZE
+ self.max_served_prefix = max_served_prefix
self.left = None
self.right = None
#When the full prefix is assigned
self.full = False
+
def find_prefix(self, prefix_size):
ret, lret, rret = [None]*3
if prefix_size > self.prefix.prefix_size and not self.full:
diff --git a/vicn/resource/ip_assignment.py b/vicn/resource/ip_assignment.py
index 62a32389..55401ecd 100644
--- a/vicn/resource/ip_assignment.py
+++ b/vicn/resource/ip_assignment.py
@@ -17,17 +17,22 @@
#
import math
+import logging
from vicn.core.resource import Resource
from netmodel.model.type import String
from vicn.core.attribute import Attribute
from vicn.resource.ip.prefix_tree import Inet6Prefix, PrefixTree, Inet4Prefix
-from vicn.core.task import inline_task
+from vicn.core.task import inline_task, async_task, EmptyTask
from vicn.core.exception import ResourceNotFound
+log = logging.getLogger(__name__)
+
class IpAssignment(Resource):
prefix = Attribute(String, mandatory=True)
control_prefix = Attribute(String, description="prefix for control plane")
+ max_prefix_size = Attribute(String,
+ description="Maximum assigned prefix size for a link")
PrefixClass = None
@@ -36,6 +41,8 @@ class IpAssignment(Resource):
self._prefix = self.PrefixClass(self.prefix)
self._prefix_tree = PrefixTree(self._prefix)
self._assigned_prefixes = {}
+ if not self.max_prefix_size:
+ self.max_prefix_size = self.PrefixClass.MAX_PREFIX_SIZE
if self.control_prefix:
self._ctrl_prefix = self.PrefixClass(self.control_prefix)
self._ctrl_prefix_it = iter(self._ctrl_prefix)
@@ -66,10 +73,11 @@ class IpAssignment(Resource):
def __get__(self):
raise ResourceNotFound
- @inline_task
+ #@inline_task
def __create__(self):
# XXX code from Channel.__create__, until Events are properly implemented.
# Iterate on channels for allocate IP addresses
+ task = EmptyTask()
for group in self.groups:
for channel in group.iter_by_type_str('channel'):
interfaces = sorted(channel.interfaces, key = lambda x : x.device_name)
@@ -77,27 +85,33 @@ class IpAssignment(Resource):
continue
min_prefix_size = math.ceil(math.log(len(channel.interfaces), 2))
- prefix_size = min(self.DEFAULT_PREFIX_SIZE, self.MAX_PREFIX_SIZE - min_prefix_size)
- prefix = iter(self.get_prefix(channel, prefix_size))
+ prefix_size = min(self.max_prefix_size,
+ self.PrefixClass.MAX_PREFIX_SIZE - min_prefix_size)
+ prefix = self.get_prefix(channel, prefix_size)
+
+ it = prefix.get_iterator()
for interface in interfaces:
- ip = next(prefix)
- print('attribute ip=', ip)
- setattr(interface, self.ATTR_ADDRESS, ip)
- setattr(interface, self.ATTR_PREFIX, prefix_size)
+ ip = next(it)
+ interface.set(self.ATTR_PREFIX, prefix_size)
+ #XXX Why do we need to create that async task?
+ #XXX Probably because the PendingValue is not created
+ #XXX in the main thread
+ @async_task
+ async def set_ip(interface, ip):
+ await interface.async_set(self.ATTR_ADDRESS, self.PrefixClass.ntoa(ip.ip_address))
+ task = task | set_ip(interface, ip)
+
+ return task
__delete__ = None
class Ipv6Assignment(IpAssignment):
PrefixClass = Inet6Prefix
- DEFAULT_PREFIX_SIZE = 64
- MAX_PREFIX_SIZE = 128
ATTR_ADDRESS = 'ip6_address'
ATTR_PREFIX = 'ip6_prefix'
class Ipv4Assignment(IpAssignment):
PrefixClass = Inet4Prefix
- DEFAULT_PREFIX_SIZE = 32
- MAX_PREFIX_SIZE = 32
ATTR_ADDRESS = 'ip4_address'
ATTR_PREFIX = 'ip4_prefix'
diff --git a/vicn/resource/linux/file.py b/vicn/resource/linux/file.py
index cddda8ed..44b4b5be 100644
--- a/vicn/resource/linux/file.py
+++ b/vicn/resource/linux/file.py
@@ -37,14 +37,16 @@ class File(Resource):
"""
Resource: File
"""
- filename = Attribute(String, description = 'Path to the file',
+ filename = Attribute(String, description = 'Path to the file',
+ key = True,
mandatory = True)
node = Attribute(Node, description = 'Node on which the file is created',
mandatory = True,
multiplicity = Multiplicity.ManyToOne,
reverse_name = 'files',
+ key = True,
reverse_description = 'Files created on the node')
- overwrite = Attribute(Bool,
+ overwrite = Attribute(Bool,
description = 'Determines whether an existing file is overwritten',
default = False)
@@ -53,13 +55,12 @@ class File(Resource):
#--------------------------------------------------------------------------
def __get__(self):
-
# UGLY
@inline_task
def not_found():
raise ResourceNotFound
- if self.overwrite:
+ if self.overwrite:
return not_found()
def is_path (rv):
diff --git a/vicn/resource/linux/keypair.py b/vicn/resource/linux/keypair.py
index a81a40d4..66c98e5b 100644
--- a/vicn/resource/linux/keypair.py
+++ b/vicn/resource/linux/keypair.py
@@ -37,7 +37,7 @@ class Keypair(Resource):
Implements a SSH keypair
"""
- node = Attribute(Node,
+ node = Attribute(Node,
description = 'Node on which the certificate is created',
mandatory = True,
multiplicity = Multiplicity.ManyToOne)
@@ -47,24 +47,24 @@ class Keypair(Resource):
#--------------------------------------------------------------------------
# Resource lifecycle
#--------------------------------------------------------------------------
-
+
@inline_task
def __initialize__(self):
self._pubkey_file = File(node = Reference(self, 'node'),
filename = self.key + '.pub',
managed = False)
- self._key_file = File(node = Reference(self, 'node'),
- filename = self.key,
+ self._key_file = File(node = Reference(self, 'node'),
+ filename = self.key,
managed = False)
def __get__(self):
return self._pubkey_file.__get__() | self._key_file.__get__()
def __create__(self):
- return BashTask(None, CMD_CREATE, {
+ return BashTask(self.node, CMD_CREATE, {
'dirname': os.path.dirname(self.key),
'self': self})
-
+
def __delete__(self):
return self._pubkey_file.__delete__() | self._key_file.__delete__()
diff --git a/vicn/resource/linux/link.py b/vicn/resource/linux/link.py
index ad77bfb9..da41fbe1 100644
--- a/vicn/resource/linux/link.py
+++ b/vicn/resource/linux/link.py
@@ -73,8 +73,10 @@ class Link(Channel):
delay = Attribute(String, description = 'Link propagation delay')
src_node = Attribute(Node, description = 'Source node',
+ key = True,
mandatory = True)
dst_node = Attribute(Node, description = 'Destination node',
+ key = True,
mandatory = True)
def __init__(self, *args, **kwargs):
@@ -89,6 +91,7 @@ class Link(Channel):
# but the resource manager has to take over for IP addresses etc.
# Being done in initialize, those attributes won't be considered as
# dependencies and will thus not block the resource state machine.
+
self._src = NonTapBaseNetDevice(node = self.src_node,
device_name = self.dst_node.name,
channel = self,
diff --git a/vicn/resource/linux/net_device.py b/vicn/resource/linux/net_device.py
index e40256ea..40d3edb7 100644
--- a/vicn/resource/linux/net_device.py
+++ b/vicn/resource/linux/net_device.py
@@ -280,6 +280,7 @@ class BaseNetDevice(Interface, Application):
description = 'Capacity for interface shaping (Mb/s)')
mac_address = Attribute(String, description = 'Mac address of the device')
ip4_address = Attribute(String, description = 'IP address of the device')
+ ip4_prefix = Attribute(Integer, description = 'Prefix for the IPv4link', default=31) #XXX 31?
ip6_address = Attribute(String, description = 'IPv6 address of the device')
ip6_prefix = Attribute(Integer, description = 'Prefix for the IPv6 link', default=64)
ip6_forwarding = Attribute(Bool, description = 'IPv6 forwarding', default = True)
diff --git a/vicn/resource/linux/package_manager.py b/vicn/resource/linux/package_manager.py
index eaf83e17..1b9d518c 100644
--- a/vicn/resource/linux/package_manager.py
+++ b/vicn/resource/linux/package_manager.py
@@ -78,6 +78,7 @@ class PackageManager(Resource):
reverse_name = 'package_manager',
reverse_auto = True,
mandatory = True,
+ key = True,
multiplicity = Multiplicity.OneToOne)
trusted = Attribute(Bool,
description="Force repository trust",
@@ -181,6 +182,7 @@ class Package(Resource):
package_name = Attribute(String, mandatory = True)
node = Attribute(Node,
mandatory = True,
+ key = True,
requirements=[
Requirement('package_manager')
])
@@ -216,6 +218,7 @@ class Packages(Resource):
names = Attribute(String, multiplicity = Multiplicity.OneToMany)
node = Attribute(Node,
mandatory = True,
+ key = True,
requirements=[
Requirement('package_manager')
])
diff --git a/vicn/resource/linux/physical.py b/vicn/resource/linux/physical.py
index d7c0b518..f71b5856 100644
--- a/vicn/resource/linux/physical.py
+++ b/vicn/resource/linux/physical.py
@@ -75,7 +75,7 @@ class Physical(Node):
"""
Require a SSH keypair to be present for authentication on nodes
"""
- return Keypair(node = None, key = FN_KEY)
+ return Keypair(node = self, key = FN_KEY)
def __initialize__(self):
if not is_local_host(self.hostname):
diff --git a/vicn/resource/lxd/lxc_container.py b/vicn/resource/lxd/lxc_container.py
index 5670d1a2..654b3bc5 100644
--- a/vicn/resource/lxd/lxc_container.py
+++ b/vicn/resource/lxd/lxc_container.py
@@ -128,9 +128,6 @@ class LxcContainer(Node):
if iface.get_type() == "dpdkdevice":
self.node.vpp_host.dpdk_devices.append(iface.pci_address)
- if 'vpp' in self.profiles:
- dummy = self.node.vpp_host.uio_devices
-
@task
def __get__(self):
client = self.node.lxd_hypervisor.client
@@ -158,7 +155,6 @@ class LxcContainer(Node):
log.debug('Container description: {}'.format(container))
client = self.node.lxd_hypervisor.client
self._container = client.containers.create(container, wait=True)
- #self._container.start(wait = True)
def _get_container_description(self):
# Base configuration
@@ -188,23 +184,6 @@ class LxcContainer(Node):
'path' : '/dev/{}'.format(device),
'type' : 'unix-char' }
-# # NETWORK (not for images)
-#
-# if not self.is_image:
-# container['config']['user.network_mode'] = 'link-local'
-# device = {
-# 'type' : 'nic',
-# 'name' : self.host_interface.device_name,
-# 'nictype' : 'bridged',
-# 'parent' : self.node.bridge.device_name,
-# }
-# device['hwaddr'] = AddressManager().get_mac(self)
-# prefix = 'veth-{}'.format(self.container_name)
-# device['host_name'] = AddressManager().get('device_name', self,
-# prefix = prefix, scope = prefix)
-#
-# container['devices'][device['name']] = device
-
# SOURCE
image_names = [alias['name'] for alias in self.node.lxd_hypervisor.aliases]
@@ -231,7 +210,6 @@ class LxcContainer(Node):
@task
def __delete__(self):
log.info("Delete container {}".format(self.container_name))
- import pdb; pdb.set_trace()
self.node.lxd_hypervisor.client.containers.remove(self.name)
#--------------------------------------------------------------------------
@@ -308,6 +286,10 @@ class LxcContainer(Node):
We don't currently use an eventually available SSH connection.
"""
+ if not self._container:
+ log.error("Executing command on uninitialized container", self, command)
+ import os; os._exit(1)
+
ret = self._container.execute(shlex.split(command))
# NOTE: pylxd documents the return value as a tuple, while it is in
diff --git a/vicn/resource/lxd/lxc_image.py b/vicn/resource/lxd/lxc_image.py
index 2cc7220d..a3a03245 100644
--- a/vicn/resource/lxd/lxc_image.py
+++ b/vicn/resource/lxd/lxc_image.py
@@ -43,22 +43,22 @@ class LxcImage(Resource):
image = Attribute(Self, description = 'image', default = None)
applications = Attribute(Application, multiplicity = Multiplicity.OneToMany)
- #---------------------------------------------------------------------------
+ #---------------------------------------------------------------------------
# Constructor / Accessors
- #---------------------------------------------------------------------------
+ #---------------------------------------------------------------------------
def __init__(self, *args, **kwargs):
self.fingerprint = None
self._tmp_container = None
super().__init__(*args, **kwargs)
- #---------------------------------------------------------------------------
+ #---------------------------------------------------------------------------
# Resource lifecycle
- #---------------------------------------------------------------------------
+ #---------------------------------------------------------------------------
@task
def __get__(self):
- aliases = [alias['name'] for images in self.node.lxd_hypervisor.client.images.all()
+ aliases = [alias['name'] for images in self.node.lxd_hypervisor.client.images.all()
for alias in images.aliases]
if not self.image in aliases:
raise ResourceNotFound
@@ -75,10 +75,8 @@ class LxcImage(Resource):
Image creation consists in setting up a temporary container, stopping
it, publishing an image of it, setting an alias, and deleting it.
"""
-
-
tmp_container.setup()
-
+
print("TODO: Installing applications...")
for application in self.applications:
print('Installing application on image')
@@ -103,13 +101,13 @@ class LxcImage(Resource):
def __delete__(self):
self.node.lxd_hypervisor.client.images.delete(self.name)
- #---------------------------------------------------------------------------
+ #---------------------------------------------------------------------------
# Public methods
- #---------------------------------------------------------------------------
+ #---------------------------------------------------------------------------
def set_alias(self):
alias_dict = {
- "description": "Ubuntu 14.04 image with ICN software already installed",
+ "description": "Ubuntu 16.04 image with ICN software already installed",
"target": self.fingerprint,
"name": self.name
}
diff --git a/vicn/resource/vpp/cicn.py b/vicn/resource/vpp/cicn.py
index be523a6c..1a68f11f 100644
--- a/vicn/resource/vpp/cicn.py
+++ b/vicn/resource/vpp/cicn.py
@@ -51,14 +51,14 @@ class CICNForwarder(Forwarder):
mandatory=True,
requirements = [Requirement('vpp')],
reverse_name='cicn')
- numa_node = Attribute(Integer,
- description = 'Numa node on which vpp will run',
+ numa_node = Attribute(Integer,
+ description = 'Numa node on which vpp will run',
default = None)
- core = Attribute(Integer,
+ core = Attribute(Integer,
description = 'Core belonging the numa node on which vpp will run',
default = None)
- enable_worker = Attribute(Bool,
- description = 'Enable one worker for packet processing',
+ enable_worker = Attribute(Bool,
+ description = 'Enable one worker for packet processing',
default = False)
#__packages__ = ['vpp-plugin-cicn']
@@ -70,14 +70,14 @@ class CICNForwarder(Forwarder):
def parse(rv):
if rv.return_value > 0 or 'cicn: not enabled' in rv.stdout:
raise ResourceNotFound
- return BashTask(self.node, CMD_VPP_CICN_GET,
+ return BashTask(self.node, CMD_VPP_CICN_GET,
lock = self.node.vpp.vppctl_lock, parse=parse)
def __create__(self):
#self.node.vpp.plugins.append("cicn")
lock = self.node.vpp.vppctl_lock
- create_task = BashTask(self.node, CMD_VPP_ENABLE_PLUGIN,
+ create_task = BashTask(self.node, CMD_VPP_ENABLE_PLUGIN,
{'plugin' : 'cicn'}, lock = lock)
face_task = EmptyTask()
@@ -89,7 +89,7 @@ class CICNForwarder(Forwarder):
return {}
for face in self.faces:
- face_task = face_task > BashTask(self.node, CMD_VPP_ADD_ICN_FACE,
+ face_task = face_task > BashTask(self.node, CMD_VPP_ADD_ICN_FACE,
{'face':face},
parse = (lambda x : parse_face(x, face)), lock = lock)
@@ -99,7 +99,7 @@ class CICNForwarder(Forwarder):
if route.node is self.node:
self.routes.append(route)
for route in self.routes:
- route_task = route_task > BashTask(self.node,
+ route_task = route_task > BashTask(self.node,
CMD_VPP_ADD_ICN_ROUTE, {'route' : route}, lock = lock)
return (wait_resource_task(self.node.vpp) > create_task) > (face_task > route_task)
diff --git a/vicn/resource/vpp/dpdk_device.py b/vicn/resource/vpp/dpdk_device.py
index 69449e48..472ee26f 100644
--- a/vicn/resource/vpp/dpdk_device.py
+++ b/vicn/resource/vpp/dpdk_device.py
@@ -27,9 +27,9 @@ class DpdkDevice(PhyInterface):
A DpdkDevice is a physical net device supported by Dpdk and with parameters
specific to VPP.
"""
- numa_node = Attribute(Integer,
+ numa_node = Attribute(Integer,
description = 'NUMA node on the same PCI bus as the DPDK card')
- socket_mem = Attribute(Integer,
- description = 'Memory used by the vpp forwarder',
+ socket_mem = Attribute(Integer,
+ description = 'Memory used by the vpp forwarder',
default = 512)
mac_address = Attribute(String)
diff --git a/vicn/resource/vpp/vpp.py b/vicn/resource/vpp/vpp.py
index f9d10703..0edbe9b8 100644
--- a/vicn/resource/vpp/vpp.py
+++ b/vicn/resource/vpp/vpp.py
@@ -55,11 +55,11 @@ class VPP(Resource):
node = Attribute(Node,
multiplicity = Multiplicity.OneToOne,
reverse_name = 'vpp')
- numa_node = Attribute(Integer,
+ numa_node = Attribute(Integer,
description = 'Numa node on which vpp will run')
- core = Attribute(Integer,
+ core = Attribute(Integer,
description = 'Core belonging the numa node on which vpp will run')
- enable_worker = Attribute(Bool,
+ enable_worker = Attribute(Bool,
description = 'Enable one worker for packet processing',
default = False)
@@ -88,8 +88,8 @@ class VPP(Resource):
return BashTask(self.node, CMD_GET)
def __subresources__(self):
- self.dpdk_setup_file = TextFile(node = self.node,
- filename = FN_VPP_DPDK_SCRIPT,
+ self.dpdk_setup_file = TextFile(node = self.node,
+ filename = FN_VPP_DPDK_SCRIPT,
overwrite = True)
return self.dpdk_setup_file
@@ -137,7 +137,7 @@ class VPP(Resource):
# Add the core on which running vpp and the dpdk parameters
setup = TPL_VPP_DPDK_DAEMON_SCRIPT + 'cpu {'
-
+
setup = setup + ''' \n main-core ''' + str(self.core)
if self.enable_worker:
@@ -145,7 +145,7 @@ class VPP(Resource):
setup = setup + '''\n corelist-workers ''' + str(cpu_worker)
setup = setup + '''\n}\n\n dpdk { '''
-
+
for dpdk_dev in dpdk_list:
setup = setup + ''' \n ''' + dpdk_dev
@@ -175,7 +175,7 @@ class VPP(Resource):
def _set_plugins(self):
cmd = None
for plugin in self.plugins:
- cmd = cmd > BashTask(self.node, CMD_VPP_ENABLE_PLUGIN,
+ cmd = cmd > BashTask(self.node, CMD_VPP_ENABLE_PLUGIN,
{'plugin' : plugin})
return cmd
diff --git a/vicn/resource/vpp/vpp_host.py b/vicn/resource/vpp/vpp_host.py
index 600d5566..954d1d32 100644
--- a/vicn/resource/vpp/vpp_host.py
+++ b/vicn/resource/vpp/vpp_host.py
@@ -55,7 +55,7 @@ class VPPHost(LinuxApplication):
Host must be configured to let vpp to work into container:
- install new apparmor profile (to let the container to read
- hugepages info in /sys/kernel/mm/hugepages)
+ hugepages info in /sys/kernel/mm/hugepages)
- set hugepages into the host
"""
@@ -96,7 +96,7 @@ class VPPHost(LinuxApplication):
overwrite = True)
startup_conf = TextFile(node = self.node,
filename = FN_VPP_DPDK_SCRIPT,
- content = TPL_VPP_DPDK_DAEMON_SCRIPT,
+ content = TPL_VPP_DPDK_DAEMON_SCRIPT,
overwrite = True)
return app_armor_file | startup_conf
@@ -111,7 +111,7 @@ class VPPHost(LinuxApplication):
def __create__(self):
modules = BashTask(self.node, CMD_INSERT_MODULES)
app_armor_reload = BashTask(self.node, CMD_APP_ARMOR_RELOAD)
- sysctl_hugepages = BashTask(self.node, CMD_SYSCTL_HUGEPAGES,
+ sysctl_hugepages = BashTask(self.node, CMD_SYSCTL_HUGEPAGES,
{'nb_hp': DEFAULT_NB_HUGEPAGES})
# Hook
@@ -126,9 +126,9 @@ class VPPHost(LinuxApplication):
create_uio = EmptyTask()
for device in self.dpdk_devices:
- create_uio = create_uio > BashTask(self.node,
+ create_uio = create_uio > BashTask(self.node,
CMD_CREATE_UIO_DEVICES, {'pci_address' : device})
-
+
return ((modules | app_armor_reload) | sysctl_hugepages) > \
(disable_vpp > create_uio)