diff options
author | Tim Rozet <trozet@redhat.com> | 2018-08-02 23:49:00 -0400 |
---|---|---|
committer | Tim Rozet <trozet@redhat.com> | 2018-08-23 18:01:16 -0400 |
commit | 4301e4cb3bd6f62caec575d30e8588b72ac626c7 (patch) | |
tree | 31f6ca88598c12d45f578a6a25b5c3b86c7d5dad /apex/tests | |
parent | dc83fb1667a1a65ad333a3aab1c2843601180b23 (diff) |
Adds deployment via snapshot
New arguments are added to allow snapshot deployment:
--snapshot, --snap-cache
The previous tripleo-quickstart code has been removed/replaced
with the snapshot option.
Snapshot deployments are supported on CentOS and Fedora, and snapshot
artifacts use a similar caching system as the standard deployment.
Snapshots are produced daily by Apex, and include latest as well as n-1
OpenStack versions. The os-odl-nofeature scenario is used for the
snapshots. Additionally multiple topology verions of Snapshots are
available. The Snapshot pulled at deploy time depends on the
deploy-settings and number of virtual-computes used at deploy time.
Since there is only one network used with snapshot deployments (admin),
there is no reason to pass in network settings for snapshot deployments.
That argument is now optional. Previously we required even in Standard
virtual deployments that the network settings be provided. However that
is also unnecessary, as we can default to the virtual network settings.
Includes minor fix to the tox.ini to allow specifying test cases
to run (useful for developers writing tests). Default behavior of
tox is unchanged.
JIRA: APEX-548
Change-Id: I1e08c4e54eac5aae99921f61ab7f69693ed12b47
Signed-off-by: Tim Rozet <trozet@redhat.com>
Diffstat (limited to 'apex/tests')
-rw-r--r-- | apex/tests/config/admin.xml | 7 | ||||
-rw-r--r-- | apex/tests/config/baremetal0.xml | 73 | ||||
-rw-r--r-- | apex/tests/config/node.yaml | 12 | ||||
-rw-r--r-- | apex/tests/config/snapshot.properties | 2 | ||||
-rw-r--r-- | apex/tests/test_apex_common_utils.py | 2 | ||||
-rw-r--r-- | apex/tests/test_apex_deploy.py | 33 | ||||
-rw-r--r-- | apex/tests/test_apex_deployment_snapshot.py | 374 | ||||
-rw-r--r-- | apex/tests/test_apex_overcloud_node.py | 191 |
8 files changed, 685 insertions, 9 deletions
diff --git a/apex/tests/config/admin.xml b/apex/tests/config/admin.xml new file mode 100644 index 00000000..69b15b1f --- /dev/null +++ b/apex/tests/config/admin.xml @@ -0,0 +1,7 @@ +<network connections='1' ipv6='yes'> + <name>admin</name> + <uuid>761c34f8-2a72-4205-8e69-5ed6626c6efa</uuid> + <forward mode='bridge'/> + <bridge name='br-admin'/> + <virtualport type='openvswitch'/> +</network> diff --git a/apex/tests/config/baremetal0.xml b/apex/tests/config/baremetal0.xml new file mode 100644 index 00000000..4ff8f65a --- /dev/null +++ b/apex/tests/config/baremetal0.xml @@ -0,0 +1,73 @@ +<domain type='kvm'> + <name>baremetal0</name> + <uuid>25bf15b6-130c-4bca-87af-e5cbc14bb454</uuid> + <memory unit='KiB'>12582912</memory> + <currentMemory unit='KiB'>12582912</currentMemory> + <vcpu placement='static'>4</vcpu> + <resource> + <partition>/machine</partition> + </resource> + <os> + <type arch='x86_64' machine='pc-i440fx-rhel7.0.0'>hvm</type> + <boot dev='hd'/> + <bootmenu enable='no'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <cpu mode='host-passthrough'/> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/libexec/qemu-kvm</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2' cache='unsafe'/> + <source file='/home/images/baremetal0.qcow2'/> + <target dev='sda' bus='sata'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='scsi' index='0' model='virtio-scsi'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </controller> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </controller> + <interface type='bridge'> + <mac address='00:5b:06:25:0c:dc'/> + <source bridge='br-admin'/> + <virtualport type='openvswitch'> + <parameters interfaceid='04b63cb9-21a9-4385-bbd6-df677a5eeecf'/> + </virtualport> + <model type='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </interface> + <serial type='pty'> + <target port='0'/> + </serial> + <console type='pty'> + <target type='serial' port='0'/> + </console> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <video> + <model type='cirrus' vram='16384' heads='1' primary='yes'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </memballoon> + </devices> + <seclabel type='dynamic' model='selinux' relabel='yes'/> + <seclabel type='dynamic' model='dac' relabel='yes'/> +</domain> diff --git a/apex/tests/config/node.yaml b/apex/tests/config/node.yaml new file mode 100644 index 00000000..e05644c9 --- /dev/null +++ b/apex/tests/config/node.yaml @@ -0,0 +1,12 @@ +--- +servers: + overcloud-controller-0.opnfvlf.org: + address: 192.0.2.28 + orig-ctl-mac: 00:5b:06:25:0c:dc + ovs-controller: tcp:192.0.2.28:6653 + ovs-managers: + - ptcp:6639:127.0.0.1 + - tcp:192.0.2.28:6640 + type: controller + user: heat-admin + vNode-name: baremetal0 diff --git a/apex/tests/config/snapshot.properties b/apex/tests/config/snapshot.properties new file mode 100644 index 00000000..64c149e2 --- /dev/null +++ b/apex/tests/config/snapshot.properties @@ -0,0 +1,2 @@ +OPNFV_SNAP_URL=artifacts.opnfv.org/apex/master/noha/apex-csit-snap-2018-08-05.tar.gz +OPNFV_SNAP_SHA512SUM=bb0c6fa0e675dcb39cfad11d81bb99f309d5cfc236e36a74d05ee813584f3e5bb92aa23dec775846317b75d574f8c86186c666f78a299c24fb68849897bdd4bc diff --git a/apex/tests/test_apex_common_utils.py b/apex/tests/test_apex_common_utils.py index 412d6f49..4c250117 100644 --- a/apex/tests/test_apex_common_utils.py +++ b/apex/tests/test_apex_common_utils.py @@ -135,7 +135,7 @@ class TestCommonUtils: assert output is not None def test_open_invalid_webpage(self): - assert_raises(urllib.request.URLError, utils.open_webpage, + assert_raises(exceptions.FetchException, utils.open_webpage, 'http://inv4lIdweb-page.com') @patch('builtins.open', a_mock_open) diff --git a/apex/tests/test_apex_deploy.py b/apex/tests/test_apex_deploy.py index 5741818a..be52c276 100644 --- a/apex/tests/test_apex_deploy.py +++ b/apex/tests/test_apex_deploy.py @@ -8,6 +8,7 @@ ############################################################################## import argparse +import os import unittest from mock import patch @@ -17,12 +18,12 @@ from mock import mock_open from apex.common.exceptions import ApexDeployException from apex.common.constants import DEFAULT_OS_VERSION -from apex.deploy import deploy_quickstart from apex.deploy import validate_cross_settings from apex.deploy import build_vms from apex.deploy import create_deploy_parser from apex.deploy import validate_deploy_args from apex.deploy import main +from apex.tests.constants import TEST_DUMMY_CONFIG from nose.tools import ( assert_is_instance, @@ -48,9 +49,6 @@ class TestDeploy(unittest.TestCase): def teardown(self): """This method is run once after _each_ test method is executed""" - def test_deloy_quickstart(self): - deploy_quickstart(None, None, None) - def test_validate_cross_settings(self): deploy_settings = {'deploy_options': {'dataplane': 'ovs'}} net_settings = Mock() @@ -85,12 +83,23 @@ class TestDeploy(unittest.TestCase): args = Mock() args.inventory_file = None args.virtual = True + args.snapshot = False + validate_deploy_args(args) + + def test_validate_snapshot_deploy_args(self): + args = Mock() + args.deploy_settings_file = os.path.join(TEST_DUMMY_CONFIG, + 'dummy-deploy-settings.yaml') + args.inventory_file = None + args.virtual = True + args.snapshot = True validate_deploy_args(args) def test_validate_deploy_args_no_virt_no_inv(self): args = Mock() args.inventory_file = 'file_name' args.virtual = False + args.snapshot = False assert_raises(ApexDeployException, validate_deploy_args, args) @patch('apex.deploy.os.path') @@ -99,12 +108,14 @@ class TestDeploy(unittest.TestCase): args = Mock() args.inventory_file = None args.virtual = True + args.snapshot = False assert_raises(ApexDeployException, validate_deploy_args, args) def test_validate_deploy_args_virt_and_inv_file(self): args = Mock() args.inventory_file = 'file_name' args.virtual = True + args.snapshot = False assert_raises(ApexDeployException, validate_deploy_args, args) @patch('apex.deploy.ApexDeployment') @@ -153,6 +164,7 @@ class TestDeploy(unittest.TestCase): args.virtual = False args.quickstart = False args.debug = False + args.snapshot = False args.upstream = True net_sets = mock_net_sets.return_value net_sets.enabled_network_list = ['external'] @@ -164,6 +176,7 @@ class TestDeploy(unittest.TestCase): mock_parsers.parse_nova_output.return_value = {'testnode1': 'test'} main() + @patch('apex.deploy.SnapshotDeployment') @patch('apex.deploy.validate_cross_settings') @patch('apex.deploy.virt_utils') @patch('apex.deploy.utils') @@ -174,14 +187,15 @@ class TestDeploy(unittest.TestCase): @patch('apex.deploy.os') @patch('apex.deploy.create_deploy_parser') @patch('builtins.open', a_mock_open, create=True) - def test_main_qs(self, mock_parser, mock_os, mock_deploy, - mock_net_sets, mock_net_env, mock_inv, mock_utils, - mock_virt_utils, mock_cross): + def test_main_snapshot(self, mock_parser, mock_os, mock_deploy, + mock_net_sets, mock_net_env, mock_inv, mock_utils, + mock_virt_utils, mock_cross, mock_snap_deployment): args = mock_parser.return_value.parse_args.return_value args.virtual = False - args.quickstart = True + args.snapshot = True args.debug = True main() + mock_snap_deployment.assert_called() @patch('apex.deploy.ApexDeployment') @patch('apex.deploy.uc_builder') @@ -237,6 +251,7 @@ class TestDeploy(unittest.TestCase): args.virt_compute_ram = None args.virt_default_ram = 12 args.upstream = True + args.snapshot = False net_sets = mock_net_sets.return_value net_sets.enabled_network_list = ['admin'] deploy_sets = mock_deploy_sets.return_value @@ -300,6 +315,7 @@ class TestDeploy(unittest.TestCase): args.virt_compute_ram = None args.virt_default_ram = 12 args.upstream = True + args.snapshot = False net_sets = mock_net_sets.return_value net_sets.enabled_network_list = ['admin'] deploy_sets = mock_deploy_sets.return_value @@ -361,6 +377,7 @@ class TestDeploy(unittest.TestCase): args.quickstart = False args.debug = False args.upstream = False + args.snapshot = False net_sets = mock_net_sets.return_value net_sets.enabled_network_list = ['external'] net_sets.__getitem__.side_effect = net_sets_dict.__getitem__ diff --git a/apex/tests/test_apex_deployment_snapshot.py b/apex/tests/test_apex_deployment_snapshot.py new file mode 100644 index 00000000..d7542585 --- /dev/null +++ b/apex/tests/test_apex_deployment_snapshot.py @@ -0,0 +1,374 @@ +############################################################################## +# Copyright (c) 2018 Tim Rozet (trozet@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 +############################################################################## + +from mock import patch +import os +import unittest +import urllib.request + +from apex.common import exceptions as exc +from apex.deployment.snapshot import SnapshotDeployment +from apex.settings.deploy_settings import DeploySettings +from apex.tests.constants import TEST_DUMMY_CONFIG + +DUMMY_SNAP_DIR = '/tmp/dummy_cache' + + +class TestSnapshotDeployment(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.deployment.snapshot.SnapshotDeployment.pull_snapshot') + @patch('apex.deployment.snapshot.libvirt.open') + @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot') + def test_init(self, mock_deploy_snap, mock_libvirt_open, mock_pull_snap): + + ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml') + ds = DeploySettings(ds_file) + d = SnapshotDeployment(deploy_settings=ds, + snap_cache_dir=DUMMY_SNAP_DIR, + fetch=True, all_in_one=False) + snap_dir = os.path.join(DUMMY_SNAP_DIR, 'queens', 'noha') + self.assertEqual(d.snap_cache_dir, snap_dir) + mock_pull_snap.assert_called() + mock_deploy_snap.assert_called() + self.assertEqual(d.ha_ext, 'noha') + + @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot') + @patch('apex.deployment.snapshot.libvirt.open') + @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot') + def test_init_allinone_no_fetch(self, mock_deploy_snap, mock_libvirt_open, + mock_pull_snap): + + ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml') + ds = DeploySettings(ds_file) + d = SnapshotDeployment(deploy_settings=ds, + snap_cache_dir=DUMMY_SNAP_DIR, + fetch=False, all_in_one=True) + snap_dir = os.path.join(DUMMY_SNAP_DIR, 'queens', 'noha-allinone') + self.assertEqual(d.snap_cache_dir, snap_dir) + mock_pull_snap.assert_not_called() + mock_deploy_snap.assert_called() + self.assertEqual(d.ha_ext, 'noha-allinone') + + @patch('apex.deployment.snapshot.utils.fetch_upstream_and_unpack') + @patch('apex.deployment.snapshot.utils.fetch_properties') + def test_pull_snapshot_is_latest(self, mock_fetch_props, + mock_fetch_artifact): + mock_fetch_props.return_value = { + 'OPNFV_SNAP_URL': 'artifacts.opnfv.org/apex/master/noha/' + 'apex-csit-snap-2018-08-05.tar.gz', + 'OPNFV_SNAP_SHA512SUM': 'bb0c6fa0e675dcb39cfad11d81bb99f309d5cfc23' + '6e36a74d05ee813584f3e5bb92aa23dec77584631' + '7b75d574f8c86186c666f78a299c24fb68849897b' + 'dd4bc' + } + SnapshotDeployment.pull_snapshot('http://dummy_url', + TEST_DUMMY_CONFIG) + mock_fetch_artifact.assert_not_called() + + @patch('apex.deployment.snapshot.utils.fetch_upstream_and_unpack') + @patch('apex.deployment.snapshot.utils.fetch_properties') + def test_pull_snapshot_fetch_props_failure(self, mock_fetch_props, + mock_fetch_artifact): + mock_fetch_props.side_effect = exc.FetchException + self.assertRaises(exc.FetchException, + SnapshotDeployment.pull_snapshot, + 'http://dummy_url', TEST_DUMMY_CONFIG) + + @patch('apex.deployment.snapshot.utils.fetch_upstream_and_unpack') + @patch('apex.deployment.snapshot.utils.fetch_properties') + def test_pull_snapshot_is_not_latest(self, mock_fetch_props, + mock_fetch_artifact): + mock_fetch_props.side_effect = [{ + 'OPNFV_SNAP_URL': 'artifacts.opnfv.org/apex/master/noha/' + 'apex-csit-snap-2018-08-05.tar.gz', + 'OPNFV_SNAP_SHA512SUM': '123c6fa0e675dcb39cfad11d81bb99f309d5cfc23' + '6e36a74d05ee813584f3e5bb92aa23dec77584631' + '7b75d574f8c86186c666f78a299c24fb68849897b' + 'dd4bc'}, + { + 'OPNFV_SNAP_URL': 'artifacts.opnfv.org/apex/master/noha/' + 'apex-csit-snap-2018-08-05.tar.gz', + 'OPNFV_SNAP_SHA512SUM': 'bb0c6fa0e675dcb39cfad11d81bb99f309d5cfc23' + '6e36a74d05ee813584f3e5bb92aa23dec77584631' + '7b75d574f8c86186c666f78a299c24fb68849897b' + 'dd4bc'}] + SnapshotDeployment.pull_snapshot('http://dummy_url', + TEST_DUMMY_CONFIG) + mock_fetch_artifact.assert_called() + + @patch('apex.deployment.snapshot.OvercloudNode') + @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot') + @patch('apex.deployment.snapshot.libvirt.open') + @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot') + def test_create_networks(self, mock_deploy_snap, mock_libvirt_open, + mock_pull_snap, mock_oc_node): + ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml') + ds = DeploySettings(ds_file) + d = SnapshotDeployment(deploy_settings=ds, + snap_cache_dir=DUMMY_SNAP_DIR, + fetch=False, all_in_one=False) + d.snap_cache_dir = TEST_DUMMY_CONFIG + conn = mock_libvirt_open('qemu:///system') + d.create_networks() + conn.networkCreateXML.assert_called() + + @patch('apex.deployment.snapshot.OvercloudNode') + @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot') + @patch('apex.deployment.snapshot.libvirt.open') + @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot') + def test_create_networks_invalid_cache(self, mock_deploy_snap, + mock_libvirt_open, mock_pull_snap, + mock_oc_node): + ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml') + ds = DeploySettings(ds_file) + d = SnapshotDeployment(deploy_settings=ds, + snap_cache_dir=DUMMY_SNAP_DIR, + fetch=False, all_in_one=False) + d.snap_cache_dir = '/doesnotexist/' + self.assertRaises(exc.SnapshotDeployException, d.create_networks) + + @patch('apex.deployment.snapshot.fnmatch') + @patch('apex.deployment.snapshot.OvercloudNode') + @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot') + @patch('apex.deployment.snapshot.libvirt.open') + @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot') + def test_create_networks_no_net_xmls(self, mock_deploy_snap, + mock_libvirt_open, mock_pull_snap, + mock_oc_node, mock_fnmatch): + ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml') + ds = DeploySettings(ds_file) + d = SnapshotDeployment(deploy_settings=ds, + snap_cache_dir=DUMMY_SNAP_DIR, + fetch=False, all_in_one=False) + d.snap_cache_dir = '/doesnotexist/' + mock_fnmatch.filter.return_value = [] + self.assertRaises(exc.SnapshotDeployException, d.create_networks) + + @patch('apex.deployment.snapshot.OvercloudNode') + @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot') + @patch('apex.deployment.snapshot.libvirt.open') + @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot') + def test_parse_and_create_nodes(self, mock_deploy_snap, mock_libvirt_open, + mock_pull_snap, mock_oc_node): + ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml') + ds = DeploySettings(ds_file) + d = SnapshotDeployment(deploy_settings=ds, + snap_cache_dir=DUMMY_SNAP_DIR, + fetch=False, all_in_one=False) + d.snap_cache_dir = TEST_DUMMY_CONFIG + node = mock_oc_node() + d.parse_and_create_nodes() + node.start.assert_called() + self.assertListEqual([node], d.oc_nodes) + + @patch('apex.deployment.snapshot.utils.parse_yaml') + @patch('apex.deployment.snapshot.OvercloudNode') + @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot') + @patch('apex.deployment.snapshot.libvirt.open') + @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot') + def test_parse_and_create_nodes_invalid_node_yaml( + self, mock_deploy_snap, mock_libvirt_open, mock_pull_snap, + mock_oc_node, mock_parse_yaml): + ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml') + ds = DeploySettings(ds_file) + d = SnapshotDeployment(deploy_settings=ds, + snap_cache_dir=DUMMY_SNAP_DIR, + fetch=False, all_in_one=False) + d.snap_cache_dir = TEST_DUMMY_CONFIG + node = mock_oc_node() + mock_parse_yaml.return_value = {'blah': 'dummy'} + self.assertRaises(exc.SnapshotDeployException, + d.parse_and_create_nodes) + node.start.assert_not_called() + + @patch('apex.deployment.snapshot.OvercloudNode') + @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot') + @patch('apex.deployment.snapshot.libvirt.open') + @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot') + def test_get_controllers(self, mock_deploy_snap, mock_libvirt_open, + mock_pull_snap, mock_oc_node): + ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml') + ds = DeploySettings(ds_file) + d = SnapshotDeployment(deploy_settings=ds, + snap_cache_dir=DUMMY_SNAP_DIR, + fetch=False, all_in_one=False) + d.snap_cache_dir = TEST_DUMMY_CONFIG + node = mock_oc_node() + node.role = 'controller' + d.oc_nodes = [node] + self.assertListEqual(d.get_controllers(), [node]) + + @patch('apex.deployment.snapshot.OvercloudNode') + @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot') + @patch('apex.deployment.snapshot.libvirt.open') + @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot') + def test_get_controllers_none(self, mock_deploy_snap, mock_libvirt_open, + mock_pull_snap, mock_oc_node): + ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml') + ds = DeploySettings(ds_file) + d = SnapshotDeployment(deploy_settings=ds, + snap_cache_dir=DUMMY_SNAP_DIR, + fetch=False, all_in_one=False) + d.snap_cache_dir = TEST_DUMMY_CONFIG + node = mock_oc_node() + node.role = 'compute' + d.oc_nodes = [node] + self.assertListEqual(d.get_controllers(), []) + + @patch('apex.deployment.snapshot.SnapshotDeployment.get_controllers') + @patch('apex.deployment.snapshot.time') + @patch('apex.deployment.snapshot.socket') + @patch('apex.deployment.snapshot.OvercloudNode') + @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot') + @patch('apex.deployment.snapshot.libvirt.open') + @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot') + def test_is_openstack_up(self, mock_deploy_snap, mock_libvirt_open, + mock_pull_snap, mock_oc_node, mock_socket, + mock_time, mock_get_ctrls): + ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml') + ds = DeploySettings(ds_file) + d = SnapshotDeployment(deploy_settings=ds, + snap_cache_dir=DUMMY_SNAP_DIR, + fetch=False, all_in_one=False) + d.snap_cache_dir = TEST_DUMMY_CONFIG + node = mock_oc_node() + node.ip = '123.123.123.123' + node.name = 'dummy-controller-0' + mock_get_ctrls.return_value = [node] + sock = mock_socket.socket(mock_socket.AF_INET, mock_socket.SOCK_STREAM) + sock.connect_ex.return_value = 0 + self.assertTrue(d.is_service_up('openstack')) + + @patch('apex.deployment.snapshot.SnapshotDeployment.get_controllers') + @patch('apex.deployment.snapshot.time') + @patch('apex.deployment.snapshot.socket') + @patch('apex.deployment.snapshot.OvercloudNode') + @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot') + @patch('apex.deployment.snapshot.libvirt.open') + @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot') + def test_is_openstack_up_false(self, mock_deploy_snap, mock_libvirt_open, + mock_pull_snap, mock_oc_node, mock_socket, + mock_time, mock_get_ctrls): + ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml') + ds = DeploySettings(ds_file) + d = SnapshotDeployment(deploy_settings=ds, + snap_cache_dir=DUMMY_SNAP_DIR, + fetch=False, all_in_one=False) + d.snap_cache_dir = TEST_DUMMY_CONFIG + node = mock_oc_node() + node.ip = '123.123.123.123' + node.name = 'dummy-controller-0' + mock_get_ctrls.return_value = [node] + sock = mock_socket.socket(mock_socket.AF_INET, mock_socket.SOCK_STREAM) + sock.connect_ex.return_value = 1 + self.assertFalse(d.is_service_up('openstack')) + + @patch('apex.deployment.snapshot.SnapshotDeployment.get_controllers') + @patch('apex.deployment.snapshot.time') + @patch('apex.deployment.snapshot.utils') + @patch('apex.deployment.snapshot.OvercloudNode') + @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot') + @patch('apex.deployment.snapshot.libvirt.open') + @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot') + def test_is_opendaylight_up(self, mock_deploy_snap, mock_libvirt_open, + mock_pull_snap, mock_oc_node, mock_utils, + mock_time, mock_get_ctrls): + ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml') + ds = DeploySettings(ds_file) + d = SnapshotDeployment(deploy_settings=ds, + snap_cache_dir=DUMMY_SNAP_DIR, + fetch=False, all_in_one=False) + d.snap_cache_dir = TEST_DUMMY_CONFIG + node = mock_oc_node() + node.ip = '123.123.123.123' + node.name = 'dummy-controller-0' + mock_get_ctrls.return_value = [node] + mock_utils.open_webpage.return_value = 0 + self.assertTrue(d.is_service_up('opendaylight')) + + @patch('apex.deployment.snapshot.SnapshotDeployment.get_controllers') + @patch('apex.deployment.snapshot.time') + @patch('apex.deployment.snapshot.utils') + @patch('apex.deployment.snapshot.OvercloudNode') + @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot') + @patch('apex.deployment.snapshot.libvirt.open') + @patch('apex.deployment.snapshot.SnapshotDeployment.deploy_snapshot') + def test_is_opendaylight_up_false(self, mock_deploy_snap, + mock_libvirt_open, mock_pull_snap, + mock_oc_node, mock_utils, + mock_time, mock_get_ctrls): + ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml') + ds = DeploySettings(ds_file) + d = SnapshotDeployment(deploy_settings=ds, + snap_cache_dir=DUMMY_SNAP_DIR, + fetch=False, all_in_one=False) + d.snap_cache_dir = TEST_DUMMY_CONFIG + node = mock_oc_node() + node.ip = '123.123.123.123' + node.name = 'dummy-controller-0' + mock_get_ctrls.return_value = [node] + mock_utils.open_webpage.side_effect = urllib.request.URLError( + reason='blah') + self.assertFalse(d.is_service_up('opendaylight')) + + @patch('apex.deployment.snapshot.os.path.isfile') + @patch('apex.deployment.snapshot.SnapshotDeployment.is_service_up') + @patch('apex.deployment.snapshot.SnapshotDeployment' + '.parse_and_create_nodes') + @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot') + @patch('apex.deployment.snapshot.libvirt.open') + @patch('apex.deployment.snapshot.SnapshotDeployment.create_networks') + def test_deploy_snapshot(self, mock_create_networks, mock_libvirt_open, + mock_pull_snap, mock_parse_create, + mock_service_up, mock_is_file): + mock_is_file.return_value = True + ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml') + ds = DeploySettings(ds_file) + SnapshotDeployment(deploy_settings=ds, snap_cache_dir=DUMMY_SNAP_DIR, + fetch=False, all_in_one=False) + mock_parse_create.assert_called() + mock_create_networks.assert_called() + mock_service_up.assert_called() + + @patch('apex.deployment.snapshot.os.path.isfile') + @patch('apex.deployment.snapshot.SnapshotDeployment.is_service_up') + @patch('apex.deployment.snapshot.SnapshotDeployment' + '.parse_and_create_nodes') + @patch('apex.deployment.snapshot.SnapshotDeployment.pull_snapshot') + @patch('apex.deployment.snapshot.libvirt.open') + @patch('apex.deployment.snapshot.SnapshotDeployment.create_networks') + def test_deploy_snapshot_services_down(self, mock_create_networks, + mock_libvirt_open, + mock_pull_snap, mock_parse_create, + mock_service_up, mock_is_file): + mock_is_file.return_value = True + ds_file = os.path.join(TEST_DUMMY_CONFIG, 'dummy-deploy-settings.yaml') + ds = DeploySettings(ds_file) + mock_service_up.return_value = False + self.assertRaises(exc.SnapshotDeployException, + SnapshotDeployment, + ds, DUMMY_SNAP_DIR, False, False) + + mock_service_up.side_effect = [True, False] + self.assertRaises(exc.SnapshotDeployException, + SnapshotDeployment, + ds, DUMMY_SNAP_DIR, False, False) diff --git a/apex/tests/test_apex_overcloud_node.py b/apex/tests/test_apex_overcloud_node.py new file mode 100644 index 00000000..4c67b1d8 --- /dev/null +++ b/apex/tests/test_apex_overcloud_node.py @@ -0,0 +1,191 @@ +############################################################################## +# Copyright (c) 2018 Tim Rozet (trozet@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 +############################################################################## + +from libvirt import libvirtError +from mock import patch +from mock import MagicMock +import os +import unittest +import urllib.request + +from apex.common import exceptions as exc +from apex.overcloud.node import OvercloudNode +from apex.settings.deploy_settings import DeploySettings +from apex.tests.constants import TEST_DUMMY_CONFIG + +DUMMY_SNAP_DIR = '/tmp/dummy_cache' + + +class TestSnapshotDeployment(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.overcloud.node.OvercloudNode.create') + @patch('apex.overcloud.node.os.path.isfile') + @patch('apex.overcloud.node.libvirt.open') + def test_init(self, mock_libvirt_open, mock_is_file, mock_node_create): + mock_is_file.return_value = True + OvercloudNode(role='controller', ip='123.123.123.123', + ovs_ctrlrs=None, ovs_mgrs=None, + name='dummy-controller-0', node_xml='dummynode.xml', + disk_img='dummy.qcow2') + mock_node_create.assert_called() + + @patch('apex.overcloud.node.OvercloudNode.create') + @patch('apex.overcloud.node.libvirt.open') + def test_init_invalid_files(self, mock_libvirt_open, mock_node_create): + self.assertRaises(exc.OvercloudNodeException, + OvercloudNode, 'controller', '123.123.123', + None, None, 'dummy-controller-0', 'dummynode.xml', + 'dummy.qcow2') + + @patch('apex.overcloud.node.shutil.copyfile') + @patch('apex.overcloud.node.OvercloudNode.create') + @patch('apex.overcloud.node.os.path.isfile') + @patch('apex.overcloud.node.libvirt.open') + def test_configure_disk(self, mock_libvirt_open, mock_is_file, + mock_node_create, mock_copy): + mock_is_file.return_value = True + node = OvercloudNode(role='controller', ip='123.123.123.123', + ovs_ctrlrs=None, ovs_mgrs=None, + name='dummy-controller-0', + node_xml='dummynode.xml', + disk_img='dummy.qcow2') + conn = mock_libvirt_open.return_value + conn.storagePoolLookupByName.return_value.XMLDesc.return_value = """ + <pool type='dir'> + <target> + <path>/var/lib/libvirt/images</path> + </target> + </pool> + """ + node._configure_disk('dummy.qcow2') + mock_copy.assert_called() + self.assertEqual(node.disk_img, '/var/lib/libvirt/images/dummy.qcow2') + + @patch('apex.overcloud.node.shutil.copyfile') + @patch('apex.overcloud.node.OvercloudNode.create') + @patch('apex.overcloud.node.os.path.isfile') + @patch('apex.overcloud.node.libvirt.open') + def test_configure_disk_bad_path(self, mock_libvirt_open, mock_is_file, + mock_node_create, mock_copy): + mock_is_file.return_value = True + node = OvercloudNode(role='controller', ip='123.123.123.123', + ovs_ctrlrs=None, ovs_mgrs=None, + name='dummy-controller-0', + node_xml='dummynode.xml', + disk_img='dummy.qcow2') + conn = mock_libvirt_open.return_value + conn.storagePoolLookupByName.return_value.XMLDesc.return_value = """ + <pool type='dir'> + <target> + </target> + </pool> + """ + self.assertRaises(exc.OvercloudNodeException, + node._configure_disk, 'dummy.qcow2') + + @patch('apex.overcloud.node.shutil.copyfile') + @patch('apex.overcloud.node.OvercloudNode.create') + @patch('apex.overcloud.node.os.path.isfile') + @patch('apex.overcloud.node.libvirt.open') + def test_configure_disk_no_pool(self, mock_libvirt_open, mock_is_file, + mock_node_create, mock_copy): + mock_is_file.return_value = True + node = OvercloudNode(role='controller', ip='123.123.123.123', + ovs_ctrlrs=None, ovs_mgrs=None, + name='dummy-controller-0', + node_xml='dummynode.xml', + disk_img='dummy.qcow2') + conn = mock_libvirt_open.return_value + conn.storagePoolLookupByName.return_value = None + self.assertRaises(exc.OvercloudNodeException, + node._configure_disk, 'dummy.qcow2') + + @patch('apex.overcloud.node.distro.linux_distribution') + def test_update_xml(self, mock_linux_distro): + mock_linux_distro.return_value = ['Fedora'] + xml_file = os.path.join(TEST_DUMMY_CONFIG, 'baremetal0.xml') + with open(xml_file, 'r') as fh: + xml = fh.read() + new_xml = OvercloudNode._update_xml( + xml=xml, disk_path='/dummy/disk/path/blah.qcow2') + self.assertIn('/dummy/disk/path/blah.qcow2', new_xml) + self.assertIn('/usr/bin/qemu-kvm', new_xml) + + @patch('apex.overcloud.node.distro.linux_distribution') + def test_update_xml_no_disk(self, mock_linux_distro): + mock_linux_distro.return_value = ['Fedora'] + xml_file = os.path.join(TEST_DUMMY_CONFIG, 'baremetal0.xml') + with open(xml_file, 'r') as fh: + xml = fh.read() + new_xml = OvercloudNode._update_xml(xml=xml) + self.assertIn('/home/images/baremetal0.qcow2', new_xml) + self.assertIn('/usr/bin/qemu-kvm', new_xml) + + @patch('apex.overcloud.node.OvercloudNode._update_xml') + @patch('apex.overcloud.node.OvercloudNode._configure_disk') + @patch('apex.overcloud.node.libvirt.open') + @patch('apex.overcloud.node.os.path.isfile') + def test_create(self, mock_isfile, mock_libvirt_conn, mock_configure_disk, + mock_update_xml): + mock_isfile.return_value = True + domain = mock_libvirt_conn.return_value.defineXML.return_value + node = OvercloudNode(role='controller', ip='123.123.123.123', + ovs_ctrlrs=None, ovs_mgrs=None, + name='dummy-controller-0', + node_xml=os.path.join(TEST_DUMMY_CONFIG, + 'baremetal0.xml'), + disk_img='dummy.qcow2') + self.assertIs(node.vm, domain) + + @patch('apex.overcloud.node.OvercloudNode._update_xml') + @patch('apex.overcloud.node.OvercloudNode._configure_disk') + @patch('apex.overcloud.node.libvirt.open') + @patch('apex.overcloud.node.os.path.isfile') + def test_start(self, mock_isfile, mock_libvirt_conn, mock_configure_disk, + mock_update_xml): + mock_isfile.return_value = True + domain = mock_libvirt_conn.return_value.defineXML.return_value + node = OvercloudNode(role='controller', ip='123.123.123.123', + ovs_ctrlrs=None, ovs_mgrs=None, + name='dummy-controller-0', + node_xml=os.path.join(TEST_DUMMY_CONFIG, + 'baremetal0.xml'), + disk_img='dummy.qcow2') + node.start() + domain.create.assert_called() + + @patch('apex.overcloud.node.OvercloudNode._update_xml') + @patch('apex.overcloud.node.OvercloudNode._configure_disk') + @patch('apex.overcloud.node.libvirt.open') + @patch('apex.overcloud.node.os.path.isfile') + def test_start_fail(self, mock_isfile, mock_libvirt_conn, + mock_configure_disk, mock_update_xml): + mock_isfile.return_value = True + domain = mock_libvirt_conn.return_value.defineXML.return_value + domain.create.side_effect = libvirtError('blah') + node = OvercloudNode(role='controller', ip='123.123.123.123', + ovs_ctrlrs=None, ovs_mgrs=None, + name='dummy-controller-0', + node_xml=os.path.join(TEST_DUMMY_CONFIG, + 'baremetal0.xml'), + disk_img='dummy.qcow2') + self.assertRaises(exc.OvercloudNodeException, node.start) |