diff options
-rw-r--r-- | apex/deploy.py | 2 | ||||
-rw-r--r-- | apex/overcloud/overcloud_deploy.py | 24 | ||||
-rw-r--r-- | apex/tests/test_apex_virtual_configure_vm.py | 102 | ||||
-rw-r--r-- | apex/tests/test_apex_virtual_utils.py | 101 | ||||
-rw-r--r-- | apex/undercloud/undercloud.py | 2 | ||||
-rw-r--r-- | apex/virtual/utils.py (renamed from apex/virtual/virtual_utils.py) | 8 | ||||
-rw-r--r-- | build/enable_rt_kvm.yaml | 4 | ||||
-rw-r--r-- | build/first-boot.yaml | 63 | ||||
-rwxr-xr-x | build/undercloud.sh | 3 | ||||
-rw-r--r-- | tox.ini | 2 |
10 files changed, 273 insertions, 38 deletions
diff --git a/apex/deploy.py b/apex/deploy.py index 89b0e9f5..8a3d13ed 100644 --- a/apex/deploy.py +++ b/apex/deploy.py @@ -20,7 +20,7 @@ import sys import tempfile import apex.virtual.configure_vm as vm_lib -import apex.virtual.virtual_utils as virt_utils +import apex.virtual.utils as virt_utils from apex import DeploySettings from apex import Inventory from apex import NetworkEnvironment diff --git a/apex/overcloud/overcloud_deploy.py b/apex/overcloud/overcloud_deploy.py index 395e6239..ec07b33d 100644 --- a/apex/overcloud/overcloud_deploy.py +++ b/apex/overcloud/overcloud_deploy.py @@ -20,7 +20,7 @@ import time from apex.common import constants as con from apex.common.exceptions import ApexDeployException from apex.common import parsers -from apex.virtual import virtual_utils as virt_utils +from apex.virtual import utils as virt_utils from cryptography.hazmat.primitives import serialization as \ crypto_serialization from cryptography.hazmat.primitives.asymmetric import rsa @@ -129,7 +129,6 @@ def create_deploy_cmd(ds, ns, inv, tmp_dir, ds_opts = ds['deploy_options'] deploy_options += build_sdn_env_list(ds_opts, SDN_FILE_MAP) - # TODO(trozet): make sure rt kvm file is in tht dir for k, v in OTHER_FILE_MAP.items(): if k in ds_opts and ds_opts[k]: deploy_options.append(os.path.join(con.THT_ENV_DIR, v)) @@ -453,17 +452,16 @@ def prep_env(ds, ns, inv, opnfv_env, net_env, tmp_dir): ds_opts['dataplane'] == 'ovs_dpdk': print(' OS::TripleO::ComputeExtraConfigPre: ' './ovs-dpdk-preconfig.yaml') - elif perf and perf_kern_comp: - if 'resource_registry' in line: - print("resource_registry:\n" - " OS::TripleO::NodeUserData: first-boot.yaml") - elif 'NovaSchedulerDefaultFilters' in line: - print(" NovaSchedulerDefaultFilters: 'RamFilter," - "ComputeFilter,AvailabilityZoneFilter," - "ComputeCapabilitiesFilter,ImagePropertiesFilter," - "NUMATopologyFilter'") - else: - print(line) + elif ((perf and perf_kern_comp) or ds_opts.get('rt_kvm')) and \ + 'resource_registry' in line: + print("resource_registry:\n" + " OS::TripleO::NodeUserData: first-boot.yaml") + elif perf and perf_kern_comp and \ + 'NovaSchedulerDefaultFilters' in line: + print(" NovaSchedulerDefaultFilters: 'RamFilter," + "ComputeFilter,AvailabilityZoneFilter," + "ComputeCapabilitiesFilter,ImagePropertiesFilter," + "NUMATopologyFilter'") else: print(line) diff --git a/apex/tests/test_apex_virtual_configure_vm.py b/apex/tests/test_apex_virtual_configure_vm.py new file mode 100644 index 00000000..228e06d6 --- /dev/null +++ b/apex/tests/test_apex_virtual_configure_vm.py @@ -0,0 +1,102 @@ +############################################################################## +# Copyright (c) 2016 Dan Radez (dradez@redhat.com) (Red Hat) +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import libvirt +import unittest + +from mock import patch + +from apex.virtual.configure_vm import generate_baremetal_macs +from apex.virtual.configure_vm import create_vm_storage +from apex.virtual.configure_vm import create_vm + +from nose.tools import ( + assert_regexp_matches, + assert_raises, + assert_equal) + + +class TestVirtualConfigureVM(unittest.TestCase): + @classmethod + def setup_class(cls): + """This method is run once for each class before any tests are run""" + + @classmethod + def teardown_class(cls): + """This method is run once for each class _after_ all tests are run""" + + def setup(self): + """This method is run once before _each_ test method is executed""" + + def teardown(self): + """This method is run once after _each_ test method is executed""" + + def test_generate_baremetal_macs(self): + assert_regexp_matches(generate_baremetal_macs()[0], + '^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$') + + def test_generate_baremetal_macs_alot(self): + assert_equal(len(generate_baremetal_macs(127)), 127) + + def test_generate_baremetal_macs_too_many(self): + assert_raises(ValueError, generate_baremetal_macs, 128) + + @patch('apex.virtual.configure_vm.libvirt.open') + def test_create_vm_storage(self, mock_libvirt_open): + # setup mock + conn = mock_libvirt_open.return_value + pool = conn.storagePoolLookupByName.return_value + pool.isActive.return_value = 0 + # execute + create_vm_storage('test') + + @patch('apex.virtual.configure_vm.libvirt.open') + def test_create_vm_storage_pool_none(self, mock_libvirt_open): + # setup mock + conn = mock_libvirt_open.return_value + conn.storagePoolLookupByName.return_value = None + # execute + assert_raises(Exception, create_vm_storage, 'test') + + @patch('apex.virtual.configure_vm.libvirt.open') + def test_create_vm_storage_libvirt_error(self, mock_libvirt_open): + # setup mock + conn = mock_libvirt_open.return_value + pool = conn.storagePoolLookupByName.return_value + pool.storageVolLookupByName.side_effect = libvirt.libvirtError('ermsg') + # execute + assert_raises(libvirt.libvirtError, create_vm_storage, 'test') + + @patch('apex.virtual.configure_vm.libvirt.open') + def test_create_vm_storage_new_vol_none(self, mock_libvirt_open): + # setup mock + conn = mock_libvirt_open.return_value + pool = conn.storagePoolLookupByName.return_value + pool.createXML.return_value = None + # execute + assert_raises(Exception, create_vm_storage, 'test') + + @patch('apex.virtual.configure_vm.libvirt.open') + @patch('apex.virtual.configure_vm.create_vm_storage') + def test_create_vm(self, mock_create_vm_storage, + mock_libvirt_open): + create_vm('test', 'image', default_network=True, + direct_boot=True, kernel_args='test', template_dir='./build') + + @patch('apex.virtual.configure_vm.libvirt.open') + @patch('apex.virtual.configure_vm.create_vm_storage') + def test_create_vm_x86_64(self, mock_create_vm_storage, + mock_libvirt_open): + create_vm('test', 'image', arch='x86_64', template_dir='./build') + + @patch('apex.virtual.configure_vm.libvirt.open') + @patch('apex.virtual.configure_vm.create_vm_storage') + def test_create_vm_aarch64(self, mock_create_vm_storage, + mock_libvirt_open): + create_vm('test', 'image', arch='aarch64', template_dir='./build') diff --git a/apex/tests/test_apex_virtual_utils.py b/apex/tests/test_apex_virtual_utils.py new file mode 100644 index 00000000..643069f3 --- /dev/null +++ b/apex/tests/test_apex_virtual_utils.py @@ -0,0 +1,101 @@ +############################################################################## +# Copyright (c) 2016 Dan Radez (dradez@redhat.com) (Red Hat) +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import subprocess +import unittest + +from mock import patch + +from apex.virtual.utils import DEFAULT_VIRT_IP +from apex.virtual.utils import get_virt_ip +from apex.virtual.utils import generate_inventory +from apex.virtual.utils import host_setup +from apex.virtual.utils import virt_customize + +from nose.tools import ( + assert_is_instance, + assert_regexp_matches, + assert_raises, + assert_equal) + + +class TestVirtualUtils(unittest.TestCase): + @classmethod + def setup_class(cls): + """This method is run once for each class before any tests are run""" + + @classmethod + def teardown_class(cls): + """This method is run once for each class _after_ all tests are run""" + + def setup(self): + """This method is run once before _each_ test method is executed""" + + def teardown(self): + """This method is run once after _each_ test method is executed""" + + @patch('apex.virtual.utils.subprocess.check_output') + def test_get_virt_ip(self, mock_subprocess): + mock_subprocess.return_value = '<xml></xml>' + assert_equal(get_virt_ip(), DEFAULT_VIRT_IP) + + @patch('apex.virtual.utils.subprocess.check_output') + def test_get_virt_ip_not_default(self, mock_subprocess): + mock_subprocess.return_value = '''<xml> +<ip address='1.2.3.4' netmask='255.255.255.0'/> +</xml>''' + assert_equal(get_virt_ip(), '1.2.3.4') + + @patch('apex.virtual.utils.subprocess.check_output') + def test_get_virt_ip_raises(self, mock_subprocess): + mock_subprocess.side_effect = subprocess.CalledProcessError(1, 'cmd') + assert_equal(get_virt_ip(), DEFAULT_VIRT_IP) + + @patch('apex.virtual.utils.common_utils') + def test_generate_inventory(self, mock_common_utils): + assert_is_instance(generate_inventory('target_file'), dict) + + @patch('apex.virtual.utils.common_utils') + def test_generate_inventory_ha_enabled(self, mock_common_utils): + assert_is_instance(generate_inventory('target_file', ha_enabled=True), + dict) + + @patch('apex.virtual.utils.iptc') + @patch('apex.virtual.utils.subprocess.check_call') + @patch('apex.virtual.utils.vbmc_lib') + def test_host_setup(self, mock_vbmc_lib, mock_subprocess, mock_iptc): + host_setup({'test': 2468}) + mock_subprocess.assert_called_with(['vbmc', 'start', 'test']) + + @patch('apex.virtual.utils.iptc') + @patch('apex.virtual.utils.subprocess.check_call') + @patch('apex.virtual.utils.vbmc_lib') + def test_host_setup_raise_called_process_error(self, mock_vbmc_lib, + mock_subprocess, mock_iptc): + mock_subprocess.side_effect = subprocess.CalledProcessError(1, 'cmd') + assert_raises(subprocess.CalledProcessError, host_setup, {'tst': 2468}) + + @patch('apex.virtual.utils.os.path') + @patch('apex.virtual.utils.subprocess.check_output') + def test_virt_customize(self, mock_subprocess, mock_os_path): + virt_customize([{'--operation': 'arg'}], 'target') + + @patch('apex.virtual.utils.subprocess.check_output') + def test_virt_customize_file_not_found(self, mock_subprocess): + assert_raises(FileNotFoundError, + virt_customize, + [{'--operation': 'arg'}], 'target') + + @patch('apex.virtual.utils.os.path') + @patch('apex.virtual.utils.subprocess.check_output') + def test_virt_customize_raises(self, mock_subprocess, mock_os_path): + mock_subprocess.side_effect = subprocess.CalledProcessError(1, 'cmd') + assert_raises(subprocess.CalledProcessError, + virt_customize, + [{'--operation': 'arg'}], 'target') diff --git a/apex/undercloud/undercloud.py b/apex/undercloud/undercloud.py index 7b7c35f0..50035638 100644 --- a/apex/undercloud/undercloud.py +++ b/apex/undercloud/undercloud.py @@ -15,7 +15,7 @@ import shutil import subprocess import time -from apex.virtual import virtual_utils as virt_utils +from apex.virtual import utils as virt_utils from apex.virtual import configure_vm as vm_lib from apex.common import constants from apex.common import utils diff --git a/apex/virtual/virtual_utils.py b/apex/virtual/utils.py index 1fe2c399..226af1b5 100644 --- a/apex/virtual/virtual_utils.py +++ b/apex/virtual/utils.py @@ -16,7 +16,7 @@ import pprint import subprocess import xml.etree.ElementTree as ET -from apex.common import utils +from apex.common import utils as common_utils from apex.virtual import configure_vm as vm_lib from virtualbmc import manager as vbmc_lib @@ -39,7 +39,7 @@ def get_virt_ip(): tree = ET.fromstring(virsh_net_xml) ip_tag = tree.find('ip') - if ip_tag: + if ip_tag is not None: virsh_ip = ip_tag.get('address') if virsh_ip: logging.debug("Detected virsh default network ip: " @@ -95,9 +95,9 @@ def generate_inventory(target_file, ha_enabled=False, num_computes=1, tmp_node['memory'] = compute_ram inv_output['nodes']['node{}'.format(idx)] = copy.deepcopy(tmp_node) - utils.dump_yaml(inv_output, target_file) - + common_utils.dump_yaml(inv_output, target_file) logging.info('Virtual environment file created: {}'.format(target_file)) + return inv_output def host_setup(node): diff --git a/build/enable_rt_kvm.yaml b/build/enable_rt_kvm.yaml index 4601fd40..35a00d7d 100644 --- a/build/enable_rt_kvm.yaml +++ b/build/enable_rt_kvm.yaml @@ -1,5 +1,3 @@ --- parameter_defaults: - ComputeKernelArgs: 'kvmfornfv_kernel.rpm' -resource_registry: - OS::TripleO::NodeUserData: kvm4nfv-1st-boot.yaml + KVMForNFVKernelRPM: 'kvmfornfv_kernel.rpm' diff --git a/build/first-boot.yaml b/build/first-boot.yaml index 1e8921ba..582981c0 100644 --- a/build/first-boot.yaml +++ b/build/first-boot.yaml @@ -16,6 +16,15 @@ parameters: "intel_iommu=on default_hugepagesz=2MB hugepagesz=2MB hugepages=2048" type: string default: "" + KVMForNFVKernelRPM: + description: > + Name of the kvmfornfv kernel rpm. + Example: "kvmfornfv_kernel.rpm" + type: string + default: "" + ComputeHostnameFormat: + type: string + default: "" resources: userdata: @@ -33,23 +42,51 @@ resources: template: | #!/bin/bash set -x - sed 's/^\(GRUB_CMDLINE_LINUX=".*\)"/\1 $KERNEL_ARGS"/g' \ - -i /etc/default/grub ; - grub2-mkconfig -o /etc/grub2.cfg - hugepage_count=$(echo $KERNEL_ARGS | \ - grep -oP ' ?hugepages=\K[0-9]+') - if [ -z "$hugepage_count" ]; then - hugepage_count=1024 + need_reboot='false' + + if [ -n "$KERNEL_ARGS" ]; then + sed 's/^\(GRUB_CMDLINE_LINUX=".*\)"/\1 $KERNEL_ARGS"/g' \ + -i /etc/default/grub ; + grub2-mkconfig -o /etc/grub2.cfg + hugepage_count=$(echo $KERNEL_ARGS | \ + grep -oP ' ?hugepages=\K[0-9]+') + if [ -z "$hugepage_count" ]; then + hugepage_count=1024 + fi + echo vm.hugetlb_shm_group=0 >> /usr/lib/sysctl.d/00-system.conf + HPAGE_CT=$(printf "%.0f" $(echo 2.2*$hugepage_count | bc)) + echo vm.max_map_count=$HPAGE_CT >> \ + /usr/lib/sysctl.d/00-system.conf + HPAGE_CT=$(($hugepage_count * 2 * 1024 * 1024)) + echo kernel.shmmax=$HPAGE_CT >> /usr/lib/sysctl.d/00-system.conf + need_reboot='true' + fi + + if [ -n "$KVMFORNFV_KERNEL_RPM" ]; then + FORMAT=$COMPUTE_HOSTNAME_FORMAT + if [[ -z $FORMAT ]] ; then + FORMAT="compute" ; + else + # Assumption: only %index% and %stackname% are + # the variables in Host name format + FORMAT=$(echo $FORMAT | sed 's/\%index\%//g'); + FORMAT=$(echo $FORMAT | sed 's/\%stackname\%//g'); + fi + if [[ $(hostname) == *$FORMAT* ]] ; then + yum install -y /root/$KVMFORNFV_KERNEL_RPM + grub2-mkconfig -o /etc/grub2.cfg + sleep 5 + need_reboot='true' + fi fi - echo vm.hugetlb_shm_group=0 >> /usr/lib/sysctl.d/00-system.conf - HPAGE_CT=$(printf "%.0f" $(echo 2.2*$hugepage_count | bc)) - echo vm.max_map_count=$HPAGE_CT >> /usr/lib/sysctl.d/00-system.conf - HPAGE_CT=$(($hugepage_count * 2 * 1024 * 1024)) - echo kernel.shmmax=$HPAGE_CT >> /usr/lib/sysctl.d/00-system.conf - reboot + if [ "$need_reboot" == "true" ]; then + reboot + fi params: $KERNEL_ARGS: {get_param: ComputeKernelArgs} + $KVMFORNFV_KERNEL_RPM: {get_param: KVMForNFVKernelRPM} + $COMPUTE_HOSTNAME_FORMAT: {get_param: ComputeHostnameFormat} outputs: OS::stack_id: diff --git a/build/undercloud.sh b/build/undercloud.sh index bd494fb4..ecd9c9fb 100755 --- a/build/undercloud.sh +++ b/build/undercloud.sh @@ -45,8 +45,7 @@ LIBGUESTFS_BACKEND=direct virt-customize \ --run-command "cp /usr/share/instack-undercloud/undercloud.conf.sample /home/stack/undercloud.conf && chown stack:stack /home/stack/undercloud.conf" \ --upload ${BUILD_ROOT}/opnfv-environment.yaml:/home/stack/ \ --upload ${BUILD_ROOT}/first-boot.yaml:/home/stack/ \ - --upload ${BUILD_ROOT}/kvm4nfv-1st-boot.yaml:/home/stack/ \ - --upload ${BUILD_DIR}/enable_rt_kvm.yaml:/home/stack/ \ + --upload ${BUILD_DIR}/enable_rt_kvm.yaml:/usr/share/openstack-tripleo-heat-templates/environments/ \ --upload ${BUILD_ROOT}/ovs-dpdk-preconfig.yaml:/home/stack/ \ --upload ${BUILD_ROOT}/csit-environment.yaml:/home/stack/ \ --upload ${BUILD_ROOT}/virtual-environment.yaml:/home/stack/ \ @@ -13,7 +13,7 @@ commands = --cover-tests \ --cover-package=apex \ --cover-xml \ - --cover-min-percentage 90 \ + --cover-min-percentage 94 \ apex/tests coverage report |