aboutsummaryrefslogtreecommitdiffstats
path: root/vicn/resource/lxd/lxc_container.py
diff options
context:
space:
mode:
Diffstat (limited to 'vicn/resource/lxd/lxc_container.py')
-rw-r--r--vicn/resource/lxd/lxc_container.py69
1 files changed, 54 insertions, 15 deletions
diff --git a/vicn/resource/lxd/lxc_container.py b/vicn/resource/lxd/lxc_container.py
index 8c8b4816..5b1d4e3b 100644
--- a/vicn/resource/lxd/lxc_container.py
+++ b/vicn/resource/lxd/lxc_container.py
@@ -32,9 +32,11 @@ from vicn.core.exception import ResourceNotFound
from vicn.core.requirement import Requirement
from vicn.core.resource_mgr import wait_resource_task
from vicn.core.task import task, inline_task, BashTask, EmptyTask
+from vicn.core.task import inherit_parent
from vicn.resource.linux.net_device import NetDevice
from vicn.resource.node import Node
from vicn.resource.vpp.scripts import APPARMOR_VPP_PROFILE
+from vicn.resource.lxd.lxc_image import LxcImage
from vicn.resource.lxd.lxd_profile import LXD_PROFILE_DEFAULT_IFNAME
log = logging.getLogger(__name__)
@@ -54,9 +56,20 @@ CMD_GET_IP6_FWD = 'sysctl -n net.ipv6.conf.all.forwarding'
CMD_NETWORK_DHCP='dhclient {container.management_interface.device_name}'
+CMD_MOUNT_FOLDER='''
+lxc config device add {container.name} {device-name} disk source={host_path} path={container_path}
+sleep 1
+'''
+
# Type: ContainerName
-ContainerName = String(max_size = 64, ascii = True,
- forbidden = ('/', ',', ':'))
+# https://github.com/lxc/lxd/issues/1431
+# [...] all container names must be a valid hostname under the most
+#restrictive definition of this, that is, maximum 63 characters, may not contain
+#dots, may not start by a digit or dash, may not end by a dash and must be made
+#entirely of letters, digits or hyphens.
+# XXX better have a allowed property
+ContainerName = String.restrict(max_size = 63, ascii = True,
+ forbidden = ('/', ',', ':', '_'))
class LxcContainer(Node):
"""
@@ -93,9 +106,9 @@ class LxcContainer(Node):
])
profiles = Attribute(String, multiplicity = Multiplicity.OneToMany,
default = ['vicn'])
- image = Attribute(String, description = 'image', default = None)
- is_image = Attribute(Bool, defaut = False)
- pid = Attribute(Integer, description = 'PID of the container')
+ image = Attribute(LxcImage, description = 'image', default = None)
+ is_image = Attribute(Bool, default = False)
+ pid = Attribute(Integer, description = 'PID of the container', ro = True)
ip6_forwarding = Attribute(Bool, default=True)
#--------------------------------------------------------------------------
@@ -110,6 +123,7 @@ class LxcContainer(Node):
# Resource lifecycle
#--------------------------------------------------------------------------
+ @inherit_parent
@inline_task
def __initialize__(self):
"""
@@ -128,6 +142,7 @@ class LxcContainer(Node):
if iface.get_type() == "dpdkdevice":
self.node.vpp_host.dpdk_devices.append(iface.pci_address)
+ @inherit_parent
@task
def __get__(self):
client = self.node.lxd_hypervisor.client
@@ -136,6 +151,7 @@ class LxcContainer(Node):
except pylxd.exceptions.NotFound:
raise ResourceNotFound
+ @inherit_parent
def __create__(self):
"""
Make sure vpp_host is instanciated before starting the container.
@@ -153,6 +169,7 @@ class LxcContainer(Node):
def _create_container(self):
container = self._get_container_description()
log.debug('Container description: {}'.format(container))
+ print('Container description: {}'.format(container))
client = self.node.lxd_hypervisor.client
self._container = client.containers.create(container, wait=True)
@@ -188,13 +205,13 @@ class LxcContainer(Node):
# SOURCE
image_names = [alias['name'] for alias in self.node.lxd_hypervisor.aliases]
- image_exists = self.image is not None and self.image in image_names
+ image_exists = self.image.image is not None and self.image.image in image_names
if image_exists:
container['source'] = {
'type' : 'image',
'mode' : 'local',
- 'alias' : self.image,
+ 'alias' : self.image.image,
}
else:
container['source'] = {
@@ -234,6 +251,7 @@ class LxcContainer(Node):
Method: Start the container
"""
self._container.start(wait = True)
+ import time; time.sleep(1)
@task
def __method_stop__(self):
@@ -288,10 +306,35 @@ class LxcContainer(Node):
"""
if not self._container:
- log.error("Executing command on uninitialized container", self, command)
+ log.error("Executing command on uninitialized container {} {}".format(self, command))
import os; os._exit(1)
- ret = self._container.execute(shlex.split(command))
+ if 'vppctl_wrapper' in command:
+ vpp_log = '{}/vpp-{}.sh'.format(self._state.manager._base, self.name)
+ with open(vpp_log, 'a') as f:
+ print("lxc exec {} -- {}".format(self.name, command), file=f)
+
+ # XXX Workaround: pylxd 2.2.3 buggy (w/ lxd 2.14) ?
+ # But this workaround is broken with lxd 2.15 and pylxd 2.2.4 works
+ # lxc exec freezes
+ #return self.node.execute('lxc exec {} -- {}'.format(self.name, command),
+ # output = output, as_root = as_root)
+
+ print("lxc exec {} -- {}".format(self.name, command))
+ while True:
+ try:
+ ret = self._container.execute(shlex.split(command))
+ break
+ except pylxd.exceptions.NotFound:
+ print("=====> pylxd not found during {}".format(command))
+ time.sleep(1)
+ except pylxd.exceptions.ClientConnectionFailed:
+ print("=====> pylxd connection failed during {}".format(command))
+ time.sleep(1)
+ except requests.exceptions.SSLError:
+ print("=====> ssl error during {}".format(command))
+ time.sleep(1)
+
# NOTE: pylxd documents the return value as a tuple, while it is in
# fact a ContainerExecuteResult object
@@ -306,12 +349,8 @@ class LxcContainer(Node):
return ReturnValue(*args)
def _get_ip6_forwarding(self):
- def parse(rv):
- ret = {"ip6_forwarding" : False}
- if rv.stdout == "1":
- ret["ip6_forwarding"] = True
- return ret
- return BashTask(self, CMD_GET_IP6_FWD, parse=parse)
+ return BashTask(self, CMD_GET_IP6_FWD,
+ parse = lambda rv: {'ip6_forwarding' : rv.stdout == "1"})
def _set_ip6_forwarding(self):
cmd = CMD_SET_IP6_FWD if self.ip6_forwarding else CMD_UNSET_IP6_FWD