Skip recreate Daisy server VM if it exists in python 61/45461/1
authorAlex Yang <yangyang1@zte.com.cn>
Wed, 18 Oct 2017 07:17:01 +0000 (15:17 +0800)
committerAlex Yang <yangyang1@zte.com.cn>
Wed, 18 Oct 2017 07:17:01 +0000 (15:17 +0800)
Do not recreate daisy server if it exists.
Reference to the bash code in patch [1].

[1] https://gerrit.opnfv.org/gerrit/#/c/40337/

Change-Id: If472c59ea180e550f358af4a3a9c7b42e575eddc
Signed-off-by: Alex Yang <yangyang1@zte.com.cn>
deploy/daisy_server.py
deploy/deploy.py
deploy/environment.py
tests/unit/test_daisy_server.py
tests/unit/test_deploy.py
tests/unit/test_environment.py

index a899ea2..fccfbe8 100644 (file)
@@ -207,7 +207,11 @@ class DaisyServer(object):
         status = self.ssh_run('%s install' % path_join(self.remote_dir, 'opnfv.bin'))
         log_bar('Daisy installation completed ! status = %s' % status)
 
-    def prepare_configurations(self):
+    def prepare_configurations(self, deploy_file, net_file):
+        LI('Copy cluster configuration files to Daisy Server')
+        self.scp_put(deploy_file, path_join(self.remote_dir, self.deploy_file_name))
+        self.scp_put(net_file, path_join(self.remote_dir, self.net_file_name))
+
         if self.adapter != 'libvirt':
             return
         LI('Prepare some configuration files')
@@ -218,13 +222,7 @@ class DaisyServer(object):
             is_bare=1 if self.adapter == 'ipmi' else 0)
         self.ssh_run(cmd)
 
-    def prepare_cluster(self, deploy_file, net_file):
-        LI('Copy cluster configuration files to Daisy Server')
-        self.scp_put(deploy_file, path_join(self.remote_dir, self.deploy_file_name))
-        self.scp_put(net_file, path_join(self.remote_dir, self.net_file_name))
-
-        self.prepare_configurations()
-
+    def prepare_cluster(self):
         LI('Prepare cluster and PXE')
         cmd = "python {script} --dha {deploy_file} --network {net_file} --cluster \'yes\'".format(
             script=path_join(self.remote_dir, 'deploy/tempest.py'),
index 245776f..192b4ee 100644 (file)
@@ -181,16 +181,24 @@ class DaisyDeployment(object):
         return final_deploy_file, final_deploy_file_name
 
     def run(self):
-        self.daisy_env.delete_old_environment()
+        self.daisy_env.delete_old_environment(skip_daisy=self.skip_daisy)
         if self.cleanup_only:
             return
-        self.daisy_env.create_daisy_server()
+
+        if self.skip_daisy:
+            self.daisy_env.connect_daisy_server(self.remote_dir, self.bin_file,
+                                                self.deploy_file_name, self.net_file_name)
+        else:
+            self.daisy_env.create_daisy_server()
+            self.daisy_env.connect_daisy_server(self.remote_dir, self.bin_file,
+                                                self.deploy_file_name, self.net_file_name)
+            self.daisy_env.install_daisy()
+
         if self.daisy_only:
             log_bar('Create Daisy Server successfully !')
             return
-        self.daisy_env.install_daisy(self.remote_dir, self.bin_file,
-                                     self.deploy_file_name, self.net_file_name)
-        self.daisy_env.deploy(self.deploy_file, self.net_file)
+
+        self.daisy_env.deploy(self.deploy_file, self.net_file, skip_preparation=self.skip_daisy)
         log_bar('Daisy deploy successfully !')
 
 
@@ -214,6 +222,10 @@ def config_arg_parser():
                         default=path_join(WORKSPACE, 'opnfv.bin'),
                         help='OPNFV Daisy BIN File')
 
+    parser.add_argument('-S', dest='skip_daisy', action='store_true',
+                        default=False,
+                        help='DO NOT install Daisy Server again')
+
     parser.add_argument('-do', dest='daisy_only', action='store_true',
                         default=False,
                         help='Install Daisy Server only')
@@ -273,6 +285,7 @@ def parse_arguments():
         'src_deploy_file': deploy_file,
         'net_file': net_file,
         'bin_file': args.bin_file,
+        'skip_daisy': args.skip_daisy,
         'daisy_only': args.daisy_only,
         'cleanup_only': args.cleanup_only,
         'remote_dir': args.remote_dir,
index 24c1b4f..2dd61d1 100644 (file)
@@ -42,9 +42,11 @@ from utils import (
 
 CREATE_QCOW2_PATH = path_join(WORKSPACE, 'tools')
 
-VMDEPLOY_DAISY_SERVER_NET = path_join(WORKSPACE, 'templates/virtual_environment/networks/daisy.xml')
-VMDEPLOY_TARGET_NODE_NET = path_join(WORKSPACE, 'templates/virtual_environment/networks/external.xml')
-VMDEPLOY_TARGET_KEEPALIVED_NET = path_join(WORKSPACE, 'templates/virtual_environment/networks/keepalived.xml')
+VIRT_NET_TEMPLATE_PATH = path_join(WORKSPACE, 'templates/virtual_environment/networks')
+VMDEPLOY_DAISY_SERVER_NET = path_join(VIRT_NET_TEMPLATE_PATH, 'daisy.xml')
+VMDEPLOY_TARGET_NODE_NET = path_join(VIRT_NET_TEMPLATE_PATH, 'external.xml')
+VMDEPLOY_TARGET_KEEPALIVED_NET = path_join(VIRT_NET_TEMPLATE_PATH, 'keepalived.xml')
+
 VMDEPLOY_DAISY_SERVER_VM = path_join(WORKSPACE, 'templates/virtual_environment/vms/daisy.xml')
 
 BMDEPLOY_DAISY_SERVER_VM = path_join(WORKSPACE, 'templates/physical_environment/vms/daisy.xml')
@@ -52,7 +54,6 @@ BMDEPLOY_DAISY_SERVER_VM = path_join(WORKSPACE, 'templates/physical_environment/
 ALL_IN_ONE_TEMPLATE = path_join(WORKSPACE, 'templates/virtual_environment/vms/all_in_one.xml')
 CONTROLLER_TEMPLATE = path_join(WORKSPACE, 'templates/virtual_environment/vms/controller.xml')
 COMPUTE_TEMPLATE = path_join(WORKSPACE, 'templates/virtual_environment/vms/computer.xml')
-VIRT_NET_TEMPLATE_PATH = path_join(WORKSPACE, 'templates/virtual_environment/networks')
 
 
 class DaisyEnvironment(object):
@@ -109,7 +110,7 @@ class DaisyEnvironmentBase(object):
         shutil.move(image, self.daisy_server_info['image'])
         LI('Daisy Server image is created %s' % self.daisy_server_info['image'])
 
-    def install_daisy(self, remote_dir, bin_file, deploy_file_name, net_file_name):
+    def connect_daisy_server(self, remote_dir, bin_file, deploy_file_name, net_file_name):
         self.server = DaisyServer(self.daisy_server_info['name'],
                                   self.daisy_server_info['address'],
                                   self.daisy_server_info['password'],
@@ -120,14 +121,19 @@ class DaisyEnvironmentBase(object):
                                   deploy_file_name,
                                   net_file_name)
         self.server.connect()
+
+    def install_daisy(self):
         self.server.install_daisy()
 
 
 class BareMetalEnvironment(DaisyEnvironmentBase):
-    def delete_old_environment(self):
-        LW('Begin to delete old environment !')
-        self.delete_daisy_server()
-        LW('Old environment cleanup finished !')
+    def delete_old_environment(self, skip_daisy=False):
+        if skip_daisy:
+            LI('Skip deletion of old daisy server VM')
+        else:
+            LW('Begin to delete old environment !')
+            self.delete_daisy_server()
+            LW('Old environment cleanup finished !')
 
     def create_daisy_server(self):
         self.create_daisy_server_image()
@@ -157,8 +163,10 @@ class BareMetalEnvironment(DaisyEnvironmentBase):
                              node['ipmi_pass'],
                              boot_source=boot_dev)
 
-    def deploy(self, deploy_file, net_file):
-        self.server.prepare_cluster(deploy_file, net_file)
+    def deploy(self, deploy_file, net_file, skip_preparation=False):
+        if not skip_preparation:
+            self.server.prepare_configurations(deploy_file, net_file)
+        self.server.prepare_cluster()
         self.reboot_nodes(boot_dev='pxe')
         self.server.prepare_host_and_pxe()
 
@@ -274,7 +282,7 @@ class VirtualEnvironment(DaisyEnvironmentBase):
         for host in self.deploy_struct['hosts']:
             delete_vm_and_disk(host['name'])
 
-    def delete_networks(self):
+    def delete_networks(self, skip_daisy=False):
         if 'virtNetTemplatePath' in self.deploy_struct:
             path = self.deploy_struct['virtNetTemplatePath']
         else:
@@ -284,19 +292,26 @@ class VirtualEnvironment(DaisyEnvironmentBase):
             LW('Cannot find the virtual network template path %s' % path)
             return
         for f in os.listdir(path):
+            if not (skip_daisy and f == 'daisy.xml'):
                 f = path_join(path, f)
                 if os.path.isfile(f):
                     delete_virtual_network(f)
 
-    def delete_old_environment(self):
+    def delete_old_environment(self, skip_daisy=False):
         LW('Begin to delete old environment !')
         self.delete_nodes()
-        self.delete_daisy_server()
-        self.delete_networks()
+
+        if skip_daisy:
+            LI('Skip deletion of old daisy server VM and network')
+        else:
+            self.delete_daisy_server()
+        self.delete_networks(skip_daisy=skip_daisy)
         LW('Old environment cleanup finished !')
 
-    def deploy(self, deploy_file, net_file):
-        self.server.prepare_cluster(deploy_file, net_file)
+    def deploy(self, deploy_file, net_file, skip_preparation=False):
+        if not skip_preparation:
+            self.server.prepare_configurations(deploy_file, net_file)
+        self.server.prepare_cluster()
         self.create_nodes()
         self.server.copy_new_deploy_config(self.deploy_struct)
         self.server.prepare_host_and_pxe()
index 65282e8..ea9c495 100644 (file)
@@ -49,8 +49,8 @@ data3 = get_ssh_test_command_from_file(ssh_test_file_dir(), 'ssh_stream_data3.tx
     (data3, res1, expected_ret1),
     (data3, res2, expected_ret1)])
 def test_log_from_stream(data, res, expected):
-    def log_func(str):
-        print str
+    def log_func(msg):
+        print(msg)
     pre_val = daisy_server.BLOCK_SIZE
     daisy_server.BLOCK_SIZE = 16
     ret = log_from_stream(res, data, log_func)
@@ -448,8 +448,9 @@ def test_install_daisy_DaisyServer(mock_prepare_files, mock_ssh_run, tmpdir):
 
 @pytest.mark.parametrize('adapter', [
     ('libvirt'), ('ipmi')])
+@mock.patch.object(daisy_server.DaisyServer, 'scp_put')
 @mock.patch.object(daisy_server.DaisyServer, 'ssh_run')
-def test_prepare_configurations_DaisyServer(mock_ssh_run, adapter, tmpdir):
+def test_prepare_configurations_DaisyServer(mock_ssh_run, mock_scp_put, adapter, tmpdir):
     bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name)
     DaisyServerInst = DaisyServer(daisy_server_info['name'],
                                   daisy_server_info['address'],
@@ -461,25 +462,24 @@ def test_prepare_configurations_DaisyServer(mock_ssh_run, adapter, tmpdir):
                                   deploy_file_name,
                                   net_file_name)
     mock_ssh_run.return_value = 0
+    deploy_file = os.path.join(tmpdir.dirname, tmpdir.basename, deploy_file_name)
+    net_file = os.path.join(tmpdir.dirname, tmpdir.basename, net_file_name)
     cmd = 'export PYTHONPATH={python_path}; python {script} -nw {net_file} -b {is_bare}'.format(
         python_path=remote_dir,
         script=os.path.join(remote_dir, 'deploy/prepare/execute.py'),
         net_file=os.path.join(remote_dir, net_file_name),
         is_bare=1 if adapter == 'ipmi' else 0)
-    DaisyServerInst.prepare_configurations()
+    DaisyServerInst.prepare_configurations(deploy_file, net_file)
     if adapter == 'libvirt':
         DaisyServerInst.ssh_run.assert_called_once_with(cmd)
     else:
         DaisyServerInst.ssh_run.assert_not_called()
+    assert DaisyServerInst.scp_put.call_count == 2
     tmpdir.remove()
 
 
-@mock.patch.object(daisy_server.DaisyServer, 'scp_put')
-@mock.patch.object(daisy_server.DaisyServer, 'prepare_configurations')
 @mock.patch.object(daisy_server.DaisyServer, 'ssh_run')
-def test_prepare_cluster_DaisyServer(mock_scp_put,
-                                     mock_prepare_configurations,
-                                     mock_ssh_run,
+def test_prepare_cluster_DaisyServer(mock_ssh_run,
                                      tmpdir):
     bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name)
     DaisyServerInst = DaisyServer(daisy_server_info['name'],
@@ -496,12 +496,8 @@ def test_prepare_cluster_DaisyServer(mock_scp_put,
         script=os.path.join(remote_dir, 'deploy/tempest.py'),
         deploy_file=os.path.join(remote_dir, deploy_file_name),
         net_file=os.path.join(remote_dir, net_file_name))
-    deploy_file = os.path.join(tmpdir.dirname, tmpdir.basename, deploy_file_name)
-    net_file = os.path.join(tmpdir.dirname, tmpdir.basename, net_file_name)
-    DaisyServerInst.prepare_cluster(deploy_file, net_file)
+    DaisyServerInst.prepare_cluster()
     DaisyServerInst.ssh_run.assert_called_once_with(cmd, check=True)
-    DaisyServerInst.prepare_configurations.assert_called_once_with()
-    assert DaisyServerInst.scp_put.call_count == 2
     tmpdir.remove()
 
 
index db887a0..4b68316 100644 (file)
@@ -195,6 +195,7 @@ def test__construct_final_deploy_conf_in_DaisyDeployment(mock__use_pod_descripto
             'src_deploy_file': 'deploy_baremetal.yml',
             'net_file': 'network_baremetal.yml',
             'bin_file': 'opnfv.bin',
+            'skip_daisy': False,
             'daisy_only': False,
             'cleanup_only': False,
             'remote_dir': '/home/daisy',
@@ -212,6 +213,7 @@ def test__construct_final_deploy_conf_in_DaisyDeployment(mock__use_pod_descripto
             'src_deploy_file': 'deploy_baremetal.yml',
             'net_file': 'network_baremetal.yml',
             'bin_file': 'opnfv.bin',
+            'skip_daisy': False,
             'daisy_only': False,
             'cleanup_only': True,
             'remote_dir': '/home/daisy',
@@ -229,6 +231,7 @@ def test__construct_final_deploy_conf_in_DaisyDeployment(mock__use_pod_descripto
             'src_deploy_file': 'deploy_baremetal.yml',
             'net_file': 'network_baremetal.yml',
             'bin_file': 'opnfv.bin',
+            'skip_daisy': False,
             'daisy_only': True,
             'cleanup_only': False,
             'remote_dir': '/home/daisy',
@@ -242,8 +245,9 @@ def test__construct_final_deploy_conf_in_DaisyDeployment(mock__use_pod_descripto
 @mock.patch.object(environment.BareMetalEnvironment, 'delete_old_environment')
 @mock.patch.object(environment.BareMetalEnvironment, 'create_daisy_server')
 @mock.patch.object(environment.BareMetalEnvironment, 'install_daisy')
+@mock.patch.object(environment.BareMetalEnvironment, 'connect_daisy_server')
 @mock.patch.object(environment.BareMetalEnvironment, 'deploy')
-def test_run_in_DaisyDeployment(mock_deploy, mock_install_daisy,
+def test_run_in_DaisyDeployment(mock_deploy, mock_connect_daisy_server, mock_install_daisy,
                                 mock_create_daisy_server, mock_delete_old_environment,
                                 conf_file_dir, tmpdir, kwargs):
     kwargs['src_deploy_file'] = os.path.join(conf_file_dir, kwargs['src_deploy_file'])
@@ -261,12 +265,16 @@ def test_run_in_DaisyDeployment(mock_deploy, mock_install_daisy,
     if daisy_deploy.cleanup_only is False:
         mock_create_daisy_server.assert_called_once_with()
         if daisy_deploy.daisy_only is False:
-            mock_deploy.assert_called_once_with(daisy_deploy.deploy_file, daisy_deploy.net_file)
-            mock_install_daisy.assert_called_once_with(daisy_deploy.remote_dir, daisy_deploy.bin_file,
-                                                       daisy_deploy.deploy_file_name, daisy_deploy.net_file_name)
+            mock_deploy.assert_called_once_with(daisy_deploy.deploy_file,
+                                                daisy_deploy.net_file,
+                                                skip_preparation=False)
+            mock_connect_daisy_server.assert_called_once_with(daisy_deploy.remote_dir,
+                                                              daisy_deploy.bin_file,
+                                                              daisy_deploy.deploy_file_name,
+                                                              daisy_deploy.net_file_name)
+            mock_install_daisy.assert_called_once_with()
         else:
             mock_deploy.assert_not_called()
-            mock_install_daisy.assert_not_called()
     else:
         mock_create_daisy_server.assert_not_called()
     tmpdir.remove()
@@ -286,13 +294,14 @@ def test_parse_arguments(mock_confirm_dir_exists, mock_make_file_executable,
                          mock_save_log_to_file, mock_check_sudo_privilege,
                          mock_parse_args, cleanup_only, tmpdir):
     class MockArg():
-        def __init__(self, labs_dir, lab_name, pod_name, bin_file, daisy_only,
+        def __init__(self, labs_dir, lab_name, pod_name, bin_file, skip_daisy, daisy_only,
                      cleanup_only, remote_dir, work_dir, storage_dir, pxe_bridge,
                      deploy_log, scenario):
             self.labs_dir = labs_dir
             self.lab_name = lab_name
             self.pod_name = pod_name
             self.bin_file = bin_file
+            self.skip_daisy = skip_daisy
             self.daisy_only = daisy_only
             self.cleanup_only = cleanup_only
             self.remote_dir = remote_dir
@@ -315,6 +324,7 @@ def test_parse_arguments(mock_confirm_dir_exists, mock_make_file_executable,
         'src_deploy_file': deploy_file,
         'net_file': net_file,
         'bin_file': bin_file_path,
+        'skip_daisy': False,
         'daisy_only': False,
         'cleanup_only': cleanup_only,
         'remote_dir': '/home/daisy',
@@ -324,7 +334,7 @@ def test_parse_arguments(mock_confirm_dir_exists, mock_make_file_executable,
         'deploy_log': deploy_log_path,
         'scenario': 'os-nosdn-nofeature-noha'
     }
-    mockarg = MockArg('/var/tmp/securedlab', 'zte', 'pod2', bin_file_path, False, cleanup_only, '/home/daisy', '/tmp/workdir',
+    mockarg = MockArg('/var/tmp/securedlab', 'zte', 'pod2', bin_file_path, False, False, cleanup_only, '/home/daisy', '/tmp/workdir',
                       '/home/qemu/vms', 'pxebr', deploy_log_path, 'os-nosdn-nofeature-noha')
     mock_parse_args.return_value = mockarg
     ret = parse_arguments()
index aed2c73..f7cf598 100644 (file)
@@ -136,7 +136,8 @@ def test_install_daisy_DaisyEnvironmentBase(mock_install_daisy, mock_connect, tm
     DaisyEnvBaseInst = DaisyEnvironmentBase(
         deploy_struct, net_struct, adapter, pxe_bridge,
         daisy_server, work_dir, storage_dir, scenario)
-    DaisyEnvBaseInst.install_daisy(remote_dir, bin_file, deploy_file_name, net_file_name)
+    DaisyEnvBaseInst.connect_daisy_server(remote_dir, bin_file, deploy_file_name, net_file_name)
+    DaisyEnvBaseInst.install_daisy()
     mock_install_daisy.assert_called_once_with()
     mock_connect.assert_called_once_with()
     tmpdir.remove()
@@ -246,6 +247,7 @@ def test_create_daisy_server_BareMetalEnvironment(mock_create_daisy_server_vm, m
 
 @mock.patch('deploy.environment.time.sleep')
 @mock.patch.object(daisy_server.DaisyServer, 'prepare_cluster')
+@mock.patch.object(daisy_server.DaisyServer, 'prepare_configurations')
 @mock.patch.object(environment.BareMetalEnvironment, 'reboot_nodes')
 @mock.patch.object(daisy_server.DaisyServer, 'prepare_host_and_pxe')
 @mock.patch.object(daisy_server.DaisyServer, 'check_os_installation')
@@ -253,7 +255,8 @@ def test_create_daisy_server_BareMetalEnvironment(mock_create_daisy_server_vm, m
 @mock.patch.object(daisy_server.DaisyServer, 'post_deploy')
 def test_deploy_BareMetalEnvironment(mock_post_deploy, mock_check_openstack_installation,
                                      mock_check_os_installation, mock_prepare_host_and_pxe,
-                                     mock_reboot_nodes, mock_prepare_cluster,
+                                     mock_reboot_nodes, mock_prepare_configurations,
+                                     mock_prepare_cluster,
                                      mock_sleep,
                                      tmpdir):
     work_dir = os.path.join(tmpdir.dirname, tmpdir.basename, work_dir_name)
@@ -280,7 +283,8 @@ def test_deploy_BareMetalEnvironment(mock_post_deploy, mock_check_openstack_inst
         deploy_file_name,
         net_file_name)
     BareMetalEnvironmentInst.deploy(deploy_file, net_file)
-    mock_prepare_cluster.assert_called_once_with(deploy_file, net_file)
+    mock_prepare_configurations.assert_called_once_with(deploy_file, net_file)
+    mock_prepare_cluster.assert_called_once_with()
     mock_reboot_nodes.assert_called_once_with(boot_dev='pxe')
     mock_prepare_host_and_pxe.assert_called_once_with()
     mock_check_os_installation.assert_called_once_with(len(BareMetalEnvironmentInst.deploy_struct['hosts']))
@@ -537,7 +541,7 @@ def test_delete_old_environment_VirtualEnvironment(mock_delete_daisy_server,
         daisy_server, work_dir, storage_dir, scenario)
     VirtualEnvironmentInst.delete_old_environment()
     VirtualEnvironmentInst.delete_daisy_server.assert_called_once_with()
-    VirtualEnvironmentInst.delete_networks.assert_called_once_with()
+    VirtualEnvironmentInst.delete_networks.assert_called_once_with(skip_daisy=False)
     VirtualEnvironmentInst.delete_nodes.assert_called_once_with()
     tmpdir.remove()
 
@@ -550,11 +554,12 @@ def test_delete_old_environment_VirtualEnvironment(mock_delete_daisy_server,
 @mock.patch.object(environment.DaisyServer, 'prepare_host_and_pxe')
 @mock.patch.object(environment.DaisyServer, 'copy_new_deploy_config')
 @mock.patch.object(environment.DaisyServer, 'prepare_cluster')
+@mock.patch.object(environment.DaisyServer, 'prepare_configurations')
 @mock.patch.object(environment.VirtualEnvironment, '_post_deploy')
 @mock.patch.object(environment.VirtualEnvironment, 'reboot_nodes')
 @mock.patch.object(environment.VirtualEnvironment, 'create_nodes')
 def test_deploy_VirtualEnvironment(mock_create_nodes, mock_reboot_nodes,
-                                   mock__post_deploy, mock_prepare_cluster,
+                                   mock__post_deploy, mock_prepare_configurations, mock_prepare_cluster,
                                    mock_copy_new_deploy_config, mock_prepare_host_and_pxe,
                                    mock_install_virtual_nodes, mock_check_os_installation,
                                    mock_check_openstack_installation, mock_post_deploy,
@@ -587,6 +592,7 @@ def test_deploy_VirtualEnvironment(mock_create_nodes, mock_reboot_nodes,
     mock_create_nodes.assert_called_once()
     assert mock_reboot_nodes.call_count == 2
     mock__post_deploy.assert_called_once()
+    mock_prepare_configurations.assert_called_once()
     mock_prepare_cluster.assert_called_once()
     mock_copy_new_deploy_config.assert_called_once()
     mock_prepare_host_and_pxe.assert_called_once()