summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Yang <yangyang1@zte.com.cn>2017-10-18 15:17:01 +0800
committerAlex Yang <yangyang1@zte.com.cn>2017-10-18 15:17:01 +0800
commit69eeb5a35db243d90e03248e4d84ad5e25ed08f1 (patch)
tree70e348e1c1e35d79e4bd00815deac83f62bab84d
parent7e0f730d0926b5efb93fb749ddf3951266df8b9b (diff)
Skip recreate Daisy server VM if it exists in python
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>
-rw-r--r--deploy/daisy_server.py14
-rw-r--r--deploy/deploy.py23
-rw-r--r--deploy/environment.py49
-rw-r--r--tests/unit/test_daisy_server.py24
-rw-r--r--tests/unit/test_deploy.py24
-rw-r--r--tests/unit/test_environment.py16
6 files changed, 94 insertions, 56 deletions
diff --git a/deploy/daisy_server.py b/deploy/daisy_server.py
index a899ea2b..fccfbe8c 100644
--- a/deploy/daisy_server.py
+++ b/deploy/daisy_server.py
@@ -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'),
diff --git a/deploy/deploy.py b/deploy/deploy.py
index 245776fb..192b4ee4 100644
--- a/deploy/deploy.py
+++ b/deploy/deploy.py
@@ -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,
diff --git a/deploy/environment.py b/deploy/environment.py
index 24c1b4f7..2dd61d11 100644
--- a/deploy/environment.py
+++ b/deploy/environment.py
@@ -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()
diff --git a/tests/unit/test_daisy_server.py b/tests/unit/test_daisy_server.py
index 65282e82..ea9c495c 100644
--- a/tests/unit/test_daisy_server.py
+++ b/tests/unit/test_daisy_server.py
@@ -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()
diff --git a/tests/unit/test_deploy.py b/tests/unit/test_deploy.py
index db887a01..4b68316a 100644
--- a/tests/unit/test_deploy.py
+++ b/tests/unit/test_deploy.py
@@ -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()
diff --git a/tests/unit/test_environment.py b/tests/unit/test_environment.py
index aed2c73c..f7cf5985 100644
--- a/tests/unit/test_environment.py
+++ b/tests/unit/test_environment.py
@@ -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()