X-Git-Url: https://gerrit.fd.io/r/gitweb?p=csit.git;a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2FContainerUtils.py;h=1530657edfa8295d98e32fb47a6145650e7b5941;hp=4feeb8bea2e37f3ff114160e21ba834ed92db649;hb=1469b71f48bb4e397ebaa65fbaf0512be691ec49;hpb=75e2e7bbbfc1da40f8c742870ec12204846c9bf9 diff --git a/resources/libraries/python/ContainerUtils.py b/resources/libraries/python/ContainerUtils.py index 4feeb8bea2..1530657edf 100644 --- a/resources/libraries/python/ContainerUtils.py +++ b/resources/libraries/python/ContainerUtils.py @@ -19,7 +19,7 @@ from collections import OrderedDict, Counter from resources.libraries.python.ssh import SSH -from resources.libraries.python.constants import Constants +from resources.libraries.python.Constants import Constants from resources.libraries.python.topology import Topology from resources.libraries.python.VppConfigGenerator import VppConfigGenerator @@ -135,19 +135,17 @@ class ContainerManager(object): self.engine.container = self.containers[container] self.engine.execute(command) - def install_vpp_in_all_containers(self): - """Install VPP into all containers.""" + def start_vpp_in_all_containers(self): + """Start VPP in all containers.""" for container in self.containers: self.engine.container = self.containers[container] # We need to install supervisor client/server system to control VPP # as a service - self.engine.execute('apt-get update') self.engine.install_supervisor() - self.engine.install_vpp() - self.engine.restart_vpp() + self.engine.start_vpp() def restart_vpp_in_all_containers(self): - """Restart VPP on all containers.""" + """Restart VPP in all containers.""" for container in self.containers: self.engine.container = self.containers[container] self.engine.restart_vpp() @@ -167,8 +165,6 @@ class ContainerManager(object): dut_cnt = len(Counter([self.containers[container].node['host'] for container in self.containers])) mod = len(self.containers)/dut_cnt - container_vat_template = 'memif_create_{topology}.vat'.format( - topology=chain_topology) for i, container in enumerate(self.containers): mid1 = i % mod + 1 @@ -179,69 +175,157 @@ class ContainerManager(object): guest_dir = self.engine.container.mnt[0].split(':')[1] if chain_topology == 'chain': - self.engine.create_vpp_startup_config() - self.engine.create_vpp_exec_config( - container_vat_template, - mid1=mid1, mid2=mid2, sid1=sid1, sid2=sid2, - socket1='{dir}/memif-{c.name}-{sid}'. - format(c=self.engine.container, sid=sid1, dir=guest_dir), - socket2='{dir}/memif-{c.name}-{sid}'. - format(c=self.engine.container, sid=sid2, dir=guest_dir)) + self._configure_vpp_chain_l2xc(mid1=mid1, mid2=mid2, + sid1=sid1, sid2=sid2, + guest_dir=guest_dir, + **kwargs) elif chain_topology == 'cross_horiz': - try: - dut1_if = kwargs['dut1_if'] - dut2_if = kwargs['dut2_if'] - except KeyError: - raise AttributeError('DUT interfaces not specified!') - if 'DUT1' in self.engine.container.name: - if_pci = Topology.get_interface_pci_addr( - self.engine.container.node, dut1_if) - if_name = Topology.get_interface_name( - self.engine.container.node, dut1_if) - if 'DUT2' in self.engine.container.name: - if_pci = Topology.get_interface_pci_addr( - self.engine.container.node, dut2_if) - if_name = Topology.get_interface_name( - self.engine.container.node, dut2_if) - self.engine.create_vpp_startup_config_dpdk_dev(if_pci) - self.engine.create_vpp_exec_config( - container_vat_template, - mid1=mid1, sid1=sid1, if_name=if_name, - socket1='{dir}/memif-{c.name}-{sid}'. - format(c=self.engine.container, sid=sid1, dir=guest_dir)) + self._configure_vpp_cross_horiz(mid1=mid1, mid2=mid2, + sid1=sid1, sid2=sid2, + guest_dir=guest_dir, + **kwargs) elif chain_topology == 'chain_functional': - memif_rx_mode = 'interrupt' - self.engine.create_vpp_startup_config_func_dev() - self.engine.create_vpp_exec_config( - container_vat_template, - mid1=mid1, mid2=mid2, sid1=sid1, sid2=sid2, - socket1='{dir}/memif-{c.name}-{sid}'. - format(c=self.engine.container, sid=sid1, dir=guest_dir), - socket2='{dir}/memif-{c.name}-{sid}'. - format(c=self.engine.container, sid=sid2, dir=guest_dir), - rx_mode=memif_rx_mode) + self._configure_vpp_chain_functional(mid1=mid1, mid2=mid2, + sid1=sid1, sid2=sid2, + guest_dir=guest_dir, + **kwargs) elif chain_topology == 'chain_ip4': - self.engine.create_vpp_startup_config() - vif1_mac = kwargs['tg_if1_mac'] \ - if (mid1 - 1) % kwargs['nodes'] + 1 == 1 \ - else '52:54:00:00:{0:02X}:02'.format(mid1-1) - vif2_mac = kwargs['tg_if2_mac'] \ - if (mid2 - 1) % kwargs['nodes'] + 1 == kwargs['nodes'] \ - else '52:54:00:00:{0:02X}:01'.format(mid2+1) - self.engine.create_vpp_exec_config( - container_vat_template, - mid1=mid1, mid2=mid2, sid1=sid1, sid2=sid2, - socket1='{dir}/memif-{c.name}-{sid}'. - format(c=self.engine.container, sid=sid1, dir=guest_dir), - socket2='{dir}/memif-{c.name}-{sid}'. - format(c=self.engine.container, sid=sid2, dir=guest_dir), - mac1='52:54:00:00:{0:02X}:01'.format(mid1), - mac2='52:54:00:00:{0:02X}:02'.format(mid2), - vif1_mac=vif1_mac, vif2_mac=vif2_mac) + self._configure_vpp_chain_ip4(mid1=mid1, mid2=mid2, + sid1=sid1, sid2=sid2, + guest_dir=guest_dir, + **kwargs) + elif chain_topology == 'pipeline_ip4': + self._configure_vpp_pipeline_ip4(mid1=mid1, mid2=mid2, + sid1=sid1, sid2=sid2, + guest_dir=guest_dir, + **kwargs) else: - raise RuntimeError('Container topology {topology} not ' - 'implemented'. - format(topology=chain_topology)) + raise RuntimeError('Container topology {name} not implemented'. + format(name=chain_topology)) + + def _configure_vpp_chain_l2xc(self, **kwargs): + """Configure VPP in chain topology with l2xc. + + :param kwargs: Named parameters. + :param kwargs: dict + """ + self.engine.create_vpp_startup_config() + self.engine.create_vpp_exec_config( + 'memif_create_chain_l2xc.vat', + mid1=kwargs['mid1'], mid2=kwargs['mid2'], + sid1=kwargs['sid1'], sid2=kwargs['sid2'], + socket1='{guest_dir}/memif-{c.name}-{sid1}'. + format(c=self.engine.container, **kwargs), + socket2='{guest_dir}/memif-{c.name}-{sid2}'. + format(c=self.engine.container, **kwargs)) + + def _configure_vpp_cross_horiz(self, **kwargs): + """Configure VPP in cross horizontal topology (single memif). + + :param kwargs: Named parameters. + :param kwargs: dict + """ + if 'DUT1' in self.engine.container.name: + if_pci = Topology.get_interface_pci_addr( + self.engine.container.node, kwargs['dut1_if']) + if_name = Topology.get_interface_name( + self.engine.container.node, kwargs['dut1_if']) + if 'DUT2' in self.engine.container.name: + if_pci = Topology.get_interface_pci_addr( + self.engine.container.node, kwargs['dut2_if']) + if_name = Topology.get_interface_name( + self.engine.container.node, kwargs['dut2_if']) + self.engine.create_vpp_startup_config_dpdk_dev(if_pci) + self.engine.create_vpp_exec_config( + 'memif_create_cross_horizon.vat', + mid1=kwargs['mid1'], sid1=kwargs['sid1'], if_name=if_name, + socket1='{guest_dir}/memif-{c.name}-{sid1}'. + format(c=self.engine.container, **kwargs)) + + def _configure_vpp_chain_functional(self, **kwargs): + """Configure VPP in chain topology with l2xc (functional). + + :param kwargs: Named parameters. + :param kwargs: dict + """ + self.engine.create_vpp_startup_config_func_dev() + self.engine.create_vpp_exec_config( + 'memif_create_chain_functional.vat', + mid1=kwargs['mid1'], mid2=kwargs['mid2'], + sid1=kwargs['sid1'], sid2=kwargs['sid2'], + socket1='{guest_dir}/memif-{c.name}-{sid1}'. + format(c=self.engine.container, **kwargs), + socket2='{guest_dir}/memif-{c.name}-{sid2}'. + format(c=self.engine.container, **kwargs), + rx_mode='interrupt') + + def _configure_vpp_chain_ip4(self, **kwargs): + """Configure VPP in chain topology with ip4. + + :param kwargs: Named parameters. + :param kwargs: dict + """ + self.engine.create_vpp_startup_config() + + vif1_mac = kwargs['tg_if1_mac'] \ + if (kwargs['mid1'] - 1) % kwargs['nodes'] + 1 == 1 \ + else '52:54:00:00:{0:02X}:02'.format(kwargs['mid1'] - 1) + vif2_mac = kwargs['tg_if2_mac'] \ + if (kwargs['mid2'] - 1) % kwargs['nodes'] + 1 == kwargs['nodes'] \ + else '52:54:00:00:{0:02X}:01'.format(kwargs['mid2'] + 1) + self.engine.create_vpp_exec_config( + 'memif_create_chain_ip4.vat', + mid1=kwargs['mid1'], mid2=kwargs['mid2'], + sid1=kwargs['sid1'], sid2=kwargs['sid2'], + socket1='{guest_dir}/memif-{c.name}-{sid1}'. + format(c=self.engine.container, **kwargs), + socket2='{guest_dir}/memif-{c.name}-{sid2}'. + format(c=self.engine.container, **kwargs), + mac1='52:54:00:00:{0:02X}:01'.format(kwargs['mid1']), + mac2='52:54:00:00:{0:02X}:02'.format(kwargs['mid2']), + vif1_mac=vif1_mac, vif2_mac=vif2_mac) + + def _configure_vpp_pipeline_ip4(self, **kwargs): + """Configure VPP in pipeline topology with ip4. + + :param kwargs: Named parameters. + :param kwargs: dict + """ + self.engine.create_vpp_startup_config() + node = (kwargs['mid1'] - 1) % kwargs['nodes'] + 1 + mid1 = kwargs['mid1'] + mid2 = kwargs['mid2'] + role1 = 'master' + role2 = 'master' \ + if node == kwargs['nodes'] or node == kwargs['nodes'] and node == 1\ + else 'slave' + kwargs['mid2'] = kwargs['mid2'] \ + if node == kwargs['nodes'] or node == kwargs['nodes'] and node == 1\ + else kwargs['mid2'] + 1 + vif1_mac = kwargs['tg_if1_mac'] \ + if (kwargs['mid1'] - 1) % kwargs['nodes'] + 1 == 1 \ + else '52:54:00:00:{0:02X}:02'.format(kwargs['mid1'] - 1) + vif2_mac = kwargs['tg_if2_mac'] \ + if (kwargs['mid2'] - 1) % kwargs['nodes'] + 1 == kwargs['nodes'] \ + else '52:54:00:00:{0:02X}:01'.format(kwargs['mid2'] + 1) + socket1 = '{guest_dir}/memif-{c.name}-{sid1}'.\ + format(c=self.engine.container, **kwargs) \ + if node == 1 else '{guest_dir}/memif-pipe-{mid1}'.\ + format(c=self.engine.container, **kwargs) + socket2 = '{guest_dir}/memif-{c.name}-{sid2}'.\ + format(c=self.engine.container, **kwargs) \ + if node == 1 and kwargs['nodes'] == 1 or node == kwargs['nodes'] \ + else '{guest_dir}/memif-pipe-{mid2}'.\ + format(c=self.engine.container, **kwargs) + + self.engine.create_vpp_exec_config( + 'memif_create_pipeline_ip4.vat', + mid1=kwargs['mid1'], mid2=kwargs['mid2'], + sid1=kwargs['sid1'], sid2=kwargs['sid2'], + socket1=socket1, socket2=socket2, role1=role1, role2=role2, + mac1='52:54:00:00:{0:02X}:01'.format(mid1), + mac2='52:54:00:00:{0:02X}:02'.format(mid2), + vif1_mac=vif1_mac, vif2_mac=vif2_mac) def stop_all_containers(self): """Stop all containers.""" @@ -309,7 +393,9 @@ class ContainerEngine(object): def install_supervisor(self): """Install supervisord inside a container.""" - self.execute('apt-get install -y supervisor') + if isinstance(self, LXC): + self.execute('sleep 3; apt-get update') + self.execute('apt-get install -y supervisor') self.execute('echo "{config}" > {config_file} && ' 'supervisord -c {config_file}'. format( @@ -329,36 +415,19 @@ class ContainerEngine(object): 'nodaemon=false\n\n', config_file=SUPERVISOR_CONF)) - def install_vpp(self): - """Install VPP inside a container.""" - self.execute('ln -s /dev/null /etc/sysctl.d/80-vpp.conf') - # Workaround for install xenial vpp build on bionic ubuntu. - self.execute('apt-get install -y wget') - self.execute('deb=$(mktemp) && wget -O "${deb}" ' - 'http://launchpadlibrarian.net/336117627/' - 'libmbedcrypto0_2.5.1-1ubuntu1_amd64.deb && ' - 'dpkg -i "${deb}" && ' - 'rm -f "${deb}"') - self.execute('deb=$(mktemp) && wget -O "${deb}" ' - 'http://launchpadlibrarian.net/252876048/' - 'libboost-system1.58.0_1.58.0+dfsg-5ubuntu3_amd64.deb && ' - 'dpkg -i "${deb}" && ' - 'rm -f "${deb}"') - self.execute( - 'dpkg -i --force-all ' - '{guest_dir}/openvpp-testing/download_dir/*.deb'. - format(guest_dir=self.container.mnt[0].split(':')[1])) - self.execute('apt-get -f install -y') - self.execute('apt-get install -y ca-certificates') + def start_vpp(self): + """Start VPP inside a container.""" self.execute('echo "{config}" >> {config_file}'. format( config='[program:vpp]\n' 'command=/usr/bin/vpp -c /etc/vpp/startup.conf\n' + 'autostart=false\n' 'autorestart=false\n' 'redirect_stderr=true\n' 'priority=1', config_file=SUPERVISOR_CONF)) self.execute('supervisorctl reload') + self.execute('supervisorctl start vpp') def restart_vpp(self): """Restart VPP service inside a container.""" @@ -522,7 +591,7 @@ class LXC(ContainerEngine): return image = self.container.image if self.container.image else\ - "-d ubuntu -r xenial -a amd64" + "-d ubuntu -r bionic -a amd64" cmd = 'lxc-create -t download --name {c.name} -- {image} '\ '--no-validate'.format(c=self.container, image=image) @@ -541,11 +610,14 @@ class LXC(ContainerEngine): if self.container.mnt: for mount in self.container.mnt: host_dir, guest_dir = mount.split(':') + options = 'bind,create=dir' \ + if guest_dir.endswith('/') else 'bind,create=file' entry = 'lxc.mount.entry = {host_dir} '\ '/var/lib/lxc/{c.name}/rootfs{guest_dir} none ' \ - 'bind,create=dir 0 0'.format(c=self.container, - host_dir=host_dir, - guest_dir=guest_dir) + '{options} 0 0'.format(c=self.container, + host_dir=host_dir, + guest_dir=guest_dir, + options=options) ret, _, _ = self.container.ssh.exec_command_sudo( "sh -c 'echo \"{e}\" >> /var/lib/lxc/{c.name}/config'". format(e=entry, c=self.container))