Generalization of recursive function
[apex.git] / apex / tests / test_apex_overcloud_deploy.py
index 8ff98a8..6898d36 100644 (file)
@@ -25,9 +25,11 @@ from apex.overcloud.deploy import make_ssh_key
 from apex.overcloud.deploy import prep_env
 from apex.overcloud.deploy import generate_ceph_key
 from apex.overcloud.deploy import prep_storage_env
+from apex.overcloud.deploy import prep_sriov_env
 from apex.overcloud.deploy import external_network_cmds
 from apex.overcloud.deploy import create_congress_cmds
 from apex.overcloud.deploy import SDN_FILE_MAP
+from apex.overcloud.deploy import get_docker_sdn_file
 
 from nose.tools import (
     assert_regexp_matches,
@@ -72,6 +74,14 @@ class TestOvercloudDeploy(unittest.TestCase):
         res = '/usr/share/openstack-tripleo-heat-templates/environments/test'
         assert_equal(build_sdn_env_list(ds, sdn_map), [res])
 
+    def test_build_sdn_env_list_with_string(self):
+        ds = {'sdn_controller': 'opendaylight',
+              'sriov': 'xxx'}
+        prefix = '/usr/share/openstack-tripleo-heat-templates/environments'
+        res = [os.path.join(prefix, 'neutron-opendaylight.yaml'),
+               os.path.join(prefix, 'neutron-opendaylight-sriov.yaml')]
+        assert_equal(build_sdn_env_list(ds, SDN_FILE_MAP), res)
+
     def test_build_sdn_env_list_with_default(self):
         ds = {'sdn_controller': 'opendaylight',
               'vpn': True}
@@ -80,19 +90,24 @@ class TestOvercloudDeploy(unittest.TestCase):
                os.path.join(prefix, 'neutron-bgpvpn-opendaylight.yaml')]
         assert_equal(build_sdn_env_list(ds, SDN_FILE_MAP), res)
 
+    @patch('apex.overcloud.deploy.prep_sriov_env')
     @patch('apex.overcloud.deploy.prep_storage_env')
     @patch('apex.overcloud.deploy.build_sdn_env_list')
     @patch('builtins.open', mock_open())
-    def test_create_deploy_cmd(self, mock_sdn_list, mock_prep_storage):
+    def test_create_deploy_cmd(self, mock_sdn_list, mock_prep_storage,
+                               mock_prep_sriov):
         mock_sdn_list.return_value = []
-        ds = {'deploy_options': MagicMock(),
+        ds = {'deploy_options':
+              {'ha_enabled': True,
+               'congress': True,
+               'tacker': True,
+               'containers': False,
+               'barometer': True,
+               'ceph': False,
+               'sriov': False
+               },
               'global_params': MagicMock()}
-        ds['global_params'].__getitem__.side_effect = \
-            lambda i: True if i == 'ha_enabled' else MagicMock()
-        ds['deploy_options'].__getitem__.side_effect = \
-            lambda i: True if i == 'congress' else MagicMock()
-        ds['deploy_options'].__contains__.side_effect = \
-            lambda i: True if i == 'congress' else MagicMock()
+
         ns = {'ntp': ['ntp']}
         inv = MagicMock()
         inv.get_node_counts.return_value = (3, 2)
@@ -106,11 +121,50 @@ class TestOvercloudDeploy(unittest.TestCase):
         assert_in('--control-scale 3', result_cmd)
         assert_in('--compute-scale 2', result_cmd)
 
+    @patch('apex.overcloud.deploy.prep_sriov_env')
+    @patch('apex.overcloud.deploy.prep_storage_env')
+    @patch('builtins.open', mock_open())
+    def test_create_deploy_cmd_containers_sdn(self, mock_prep_storage,
+                                              mock_prep_sriov):
+        ds = {'deploy_options':
+              {'ha_enabled': True,
+               'congress': False,
+               'tacker': False,
+               'containers': True,
+               'barometer': False,
+               'ceph': True,
+               'sdn_controller': 'opendaylight',
+               'sriov': False
+               },
+              'global_params': MagicMock()}
+
+        ns = {'ntp': ['ntp']}
+        inv = MagicMock()
+        inv.get_node_counts.return_value = (3, 2)
+        virt = True
+        result_cmd = create_deploy_cmd(ds, ns, inv, '/tmp', virt)
+        assert_in('--ntp-server ntp', result_cmd)
+        assert_not_in('enable_tacker.yaml', result_cmd)
+        assert_not_in('enable_congress.yaml', result_cmd)
+        assert_not_in('enable_barometer.yaml', result_cmd)
+        assert_in('virtual-environment.yaml', result_cmd)
+        assert_in('--control-scale 3', result_cmd)
+        assert_in('--compute-scale 2', result_cmd)
+        assert_in('docker-images.yaml', result_cmd)
+        assert_in('sdn-images.yaml', result_cmd)
+        assert_in('/usr/share/openstack-tripleo-heat-templates/environments'
+                  '/docker.yaml', result_cmd)
+        assert_in('/usr/share/openstack-tripleo-heat-templates/environments/'
+                  'storage-environment.yaml', result_cmd)
+        assert_in('/usr/share/openstack-tripleo-heat-templates/environments'
+                  '/services-docker/neutron-opendaylight.yaml', result_cmd)
+
+    @patch('apex.overcloud.deploy.prep_sriov_env')
     @patch('apex.overcloud.deploy.prep_storage_env')
     @patch('apex.overcloud.deploy.build_sdn_env_list')
     @patch('builtins.open', mock_open())
     def test_create_deploy_cmd_no_ha_bm(self, mock_sdn_list,
-                                        mock_prep_storage):
+                                        mock_prep_storage, mock_prep_sriov):
         mock_sdn_list.return_value = []
         ds = {'deploy_options': MagicMock(),
               'global_params': MagicMock()}
@@ -129,9 +183,11 @@ class TestOvercloudDeploy(unittest.TestCase):
         assert_not_in('enable_congress.yaml', result_cmd)
         assert_not_in('enable_barometer.yaml', result_cmd)
 
+    @patch('apex.overcloud.deploy.prep_sriov_env')
     @patch('apex.overcloud.deploy.prep_storage_env')
     @patch('apex.overcloud.deploy.build_sdn_env_list')
-    def test_create_deploy_cmd_raises(self, mock_sdn_list, mock_prep_storage):
+    def test_create_deploy_cmd_raises(self, mock_sdn_list, mock_prep_storage,
+                                      mock_prep_sriov):
         mock_sdn_list.return_value = []
         ds = {'deploy_options': MagicMock(),
               'global_params': MagicMock()}
@@ -149,12 +205,14 @@ class TestOvercloudDeploy(unittest.TestCase):
     def test_prep_image(self, mock_os_path, mock_shutil, mock_virt_utils):
         ds_opts = {'dataplane': 'fdio',
                    'sdn_controller': 'opendaylight',
-                   'odl_version': 'master'}
+                   'odl_version': 'master',
+                   'sriov': False}
         ds = {'deploy_options': MagicMock(),
               'global_params': MagicMock()}
         ds['deploy_options'].__getitem__.side_effect = \
             lambda i: ds_opts.get(i, MagicMock())
-        prep_image(ds, 'undercloud.qcow2', '/tmp', root_pw='test')
+        ns = MagicMock()
+        prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
         mock_virt_utils.virt_customize.assert_called()
 
     @patch('apex.overcloud.deploy.virt_utils')
@@ -169,7 +227,8 @@ class TestOvercloudDeploy(unittest.TestCase):
               'global_params': MagicMock()}
         ds['deploy_options'].__getitem__.side_effect = \
             lambda i: ds_opts.get(i, MagicMock())
-        prep_image(ds, 'undercloud.qcow2', '/tmp', root_pw='test')
+        ns = MagicMock()
+        prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
         mock_virt_utils.virt_customize.assert_called()
 
     @patch('apex.overcloud.deploy.virt_utils')
@@ -188,9 +247,39 @@ class TestOvercloudDeploy(unittest.TestCase):
             lambda i: ds_opts.get(i, MagicMock())
         ds['deploy_options'].__contains__.side_effect = \
             lambda i: True if i in ds_opts else MagicMock()
-        prep_image(ds, 'undercloud.qcow2', '/tmp', root_pw='test')
+        ns = MagicMock()
+        prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
         mock_virt_utils.virt_customize.assert_called()
 
+    @patch('apex.overcloud.deploy.c_builder')
+    @patch('apex.overcloud.deploy.oc_builder')
+    @patch('apex.overcloud.deploy.virt_utils')
+    @patch('apex.overcloud.deploy.shutil')
+    @patch('apex.overcloud.deploy.os.path')
+    @patch('builtins.open', mock_open())
+    def test_prep_image_sdn_odl_upstream_containers_patches(
+            self, mock_os_path, mock_shutil, mock_virt_utils,
+            mock_oc_builder, mock_c_builder):
+        ds_opts = {'dataplane': 'ovs',
+                   'sdn_controller': 'opendaylight',
+                   'odl_version': con.DEFAULT_ODL_VERSION,
+                   'odl_vpp_netvirt': True}
+        ds = {'deploy_options': MagicMock(),
+              'global_params': MagicMock()}
+        ds['deploy_options'].__getitem__.side_effect = \
+            lambda i: ds_opts.get(i, MagicMock())
+        ds['deploy_options'].__contains__.side_effect = \
+            lambda i: True if i in ds_opts else MagicMock()
+        ns = MagicMock()
+        mock_c_builder.add_upstream_patches.return_value = ['nova-api']
+        patches = ['dummy_nova_patch']
+        rv = prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test',
+                        docker_tag='latest', patches=patches, upstream=True)
+        mock_oc_builder.inject_opendaylight.assert_called
+        mock_virt_utils.virt_customize.assert_called()
+        mock_c_builder.add_upstream_patches.assert_called
+        self.assertListEqual(sorted(rv), ['nova-api', 'opendaylight'])
+
     @patch('apex.overcloud.deploy.virt_utils')
     @patch('apex.overcloud.deploy.shutil')
     @patch('apex.overcloud.deploy.os.path')
@@ -204,7 +293,8 @@ class TestOvercloudDeploy(unittest.TestCase):
               'global_params': MagicMock()}
         ds['deploy_options'].__getitem__.side_effect = \
             lambda i: ds_opts.get(i, MagicMock())
-        prep_image(ds, 'undercloud.qcow2', '/tmp', root_pw='test')
+        ns = MagicMock()
+        prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
         mock_virt_utils.virt_customize.assert_called()
 
     @patch('apex.overcloud.deploy.virt_utils')
@@ -219,14 +309,15 @@ class TestOvercloudDeploy(unittest.TestCase):
               'global_params': MagicMock()}
         ds['deploy_options'].__getitem__.side_effect = \
             lambda i: ds_opts.get(i, MagicMock())
-        prep_image(ds, 'undercloud.qcow2', '/tmp', root_pw='test')
+        ns = MagicMock()
+        prep_image(ds, ns, 'undercloud.qcow2', '/tmp', root_pw='test')
         mock_virt_utils.virt_customize.assert_called()
 
     @patch('apex.overcloud.deploy.os.path.isfile')
     def test_prep_image_no_image(self, mock_isfile):
         mock_isfile.return_value = False
         assert_raises(ApexDeployException, prep_image,
-                      {}, 'undercloud.qcow2', '/tmp')
+                      {}, {}, 'undercloud.qcow2', '/tmp')
 
     def test_make_ssh_key(self):
         priv, pub = make_ssh_key()
@@ -246,6 +337,7 @@ class TestOvercloudDeploy(unittest.TestCase):
               {'sdn_controller': 'opendaylight',
                'odl_vpp_routing_node': 'test',
                'dataplane': 'ovs_dpdk',
+               'sriov': 'xxx',
                'performance': {'Compute': {'vpp': {'main-core': 'test',
                                                    'corelist-workers': 'test'},
                                            'ovs': {'dpdk_cores': 'test'},
@@ -288,6 +380,7 @@ class TestOvercloudDeploy(unittest.TestCase):
         ds = {'deploy_options':
               {'sdn_controller': False,
                'dataplane': 'fdio',
+               'sriov': 'xxx',
                'performance': {'Compute': {},
                                'Controller': {}}}}
         ns = {'domain_name': 'test.domain',
@@ -327,6 +420,7 @@ class TestOvercloudDeploy(unittest.TestCase):
         ds = {'deploy_options':
               {'sdn_controller': 'opendaylight',
                'dataplane': 'fdio',
+               'sriov': 'xxx',
                'dvr': True}}
         ns = {'domain_name': 'test.domain',
               'networks':
@@ -366,19 +460,106 @@ class TestOvercloudDeploy(unittest.TestCase):
                               mock_ceph_key):
         mock_fileinput.input.return_value = \
             ['CephClusterFSID', 'CephMonKey', 'CephAdminKey', 'random_key']
-        ds = {'deploy_options': MagicMock()}
-        ds['deploy_options'].__getitem__.side_effect = \
-            lambda i: '/dev/sdx' if i == 'ceph_device' else MagicMock()
-        ds['deploy_options'].__contains__.side_effect = \
-            lambda i: True if i == 'ceph_device' else MagicMock()
-        prep_storage_env(ds, '/tmp')
+        ds = {'deploy_options': {
+            'ceph_device': '/dev/sdx',
+            'containers': False
+        }}
+        ns = {}
+        prep_storage_env(ds, ns, virtual=False, tmp_dir='/tmp')
+
+    @patch('apex.overcloud.deploy.utils.edit_tht_env')
+    @patch('apex.overcloud.deploy.generate_ceph_key')
+    @patch('apex.overcloud.deploy.fileinput')
+    @patch('apex.overcloud.deploy.os.path.isfile')
+    @patch('builtins.open', mock_open())
+    def test_prep_storage_env_containers(self, mock_isfile, mock_fileinput,
+                                         mock_ceph_key, mock_edit_tht):
+        mock_fileinput.input.return_value = \
+            ['CephClusterFSID', 'CephMonKey', 'CephAdminKey', 'random_key']
+        ds = {'deploy_options': {
+              'ceph_device': '/dev/sdx',
+              'containers': True,
+              'os_version': 'master'
+              }, 'global_params': {'ha_enabled': False}}
+        ns = {'networks': {con.ADMIN_NETWORK: {'installer_vm':
+                                               {'ip': '192.0.2.1'}}}
+              }
+        prep_storage_env(ds, ns, virtual=True, tmp_dir='/tmp')
+        ceph_params = {
+            'DockerCephDaemonImage':
+                '192.0.2.1:8787/ceph/daemon:tag-build-master-luminous-centos'
+                '-7',
+            'CephPoolDefaultSize': 1,
+            'CephAnsibleExtraConfig': {
+                'centos_package_dependencies': [],
+                'ceph_osd_docker_memory_limit': '1g',
+                'ceph_mds_docker_memory_limit': '1g'
+            },
+            'CephPoolDefaultPgNum': 32,
+            'CephAnsibleDisksConfig': {
+                'devices': ['/dev/sdx'],
+                'journal_size': 512,
+                'osd_scenario': 'collocated'
+            }
+        }
+        mock_edit_tht.assert_called_with('/tmp/storage-environment.yaml',
+                                         'parameter_defaults',
+                                         ceph_params)
 
     @patch('apex.overcloud.deploy.os.path.isfile')
     @patch('builtins.open', mock_open())
     def test_prep_storage_env_raises(self, mock_isfile):
         mock_isfile.return_value = False
         ds = {'deploy_options': MagicMock()}
-        assert_raises(ApexDeployException, prep_storage_env, ds, '/tmp')
+        ns = {}
+        assert_raises(ApexDeployException, prep_storage_env, ds,
+                      ns, virtual=False, tmp_dir='/tmp')
+
+    @patch('apex.overcloud.deploy.generate_ceph_key')
+    @patch('apex.overcloud.deploy.fileinput')
+    @patch('apex.overcloud.deploy.os.path.isfile')
+    @patch('builtins.open', mock_open())
+    def test_prep_sriov_env(self, mock_isfile, mock_fileinput, mock_ceph_key):
+        ds = {'deploy_options':
+              {'sdn_controller': 'opendaylight',
+               'sriov': 'xxx'}}
+        try:
+            # Swap stdout
+            saved_stdout = sys.stdout
+            out = StringIO()
+            sys.stdout = out
+            # Run tests
+            mock_fileinput.input.return_value = \
+                ['#  NovaSchedulerDefaultFilters',
+                 '#  NovaSchedulerAvailableFilters',
+                 '#NeutronPhysicalDevMappings: "datacentre:ens20f2"',
+                 '#NeutronSriovNumVFs: \"ens20f2:5\"',
+                 '#NovaPCIPassthrough:',
+                 '#  - devname: \"ens20f2\"',
+                 '#    physical_network: \"datacentre\"']
+            prep_sriov_env(ds, '/tmp')
+            output = out.getvalue().strip()
+            assert_in('NovaSchedulerDefaultFilters', output)
+            assert_in('NovaSchedulerAvailableFilters', output)
+            assert_in('NeutronPhysicalDevMappings: \"nfv_sriov:xxx\"', output)
+            assert_in('NeutronSriovNumVFs: \"xxx:8\"', output)
+            assert_in('NovaPCIPassthrough:', output)
+            assert_in('- devname: \"xxx\"', output)
+            assert_in('physical_network: \"nfv_sriov\"', output)
+        finally:
+            # put stdout back
+            sys.stdout = saved_stdout
+
+    @patch('apex.overcloud.deploy.os.path.isfile')
+    @patch('builtins.open', mock_open())
+    def test_prep_sriov_env_raises(self, mock_isfile):
+        ds_opts = {'sriov': True}
+        ds = {'deploy_options': MagicMock()}
+        ds['deploy_options'].__getitem__.side_effect = \
+            lambda i: ds_opts.get(i, MagicMock())
+        mock_isfile.return_value = False
+        ds = {'deploy_options': MagicMock()}
+        assert_raises(ApexDeployException, prep_sriov_env, ds, '/tmp')
 
     def test_external_network_cmds(self):
         cidr = MagicMock()
@@ -427,3 +608,19 @@ class TestOvercloudDeploy(unittest.TestCase):
     def test_create_congress_cmds_raises(self, mock_parsers):
         mock_parsers.return_value.__getitem__.side_effect = KeyError()
         assert_raises(KeyError, create_congress_cmds, 'overcloud_file')
+
+    def test_get_docker_sdn_file(self):
+        ds_opts = {'ha_enabled': True,
+                   'congress': True,
+                   'tacker': True,
+                   'containers': False,
+                   'barometer': True,
+                   'ceph': False,
+                   'sdn_controller': 'opendaylight'
+                   }
+        output = get_docker_sdn_file(ds_opts)
+        self.assertEqual(output,
+                         ('/usr/share/openstack-tripleo-heat-templates'
+                          '/environments/services-docker/neutron-opendaylight'
+                          '.yaml')
+                         )