summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xci/build_rpm/build_rpms_docker.sh1
-rwxr-xr-xci/deploy/deploy.sh8
-rw-r--r--deploy/tempest.py1
-rw-r--r--docker/Dockerfile1
-rw-r--r--docs/release/installation/installation_guide.rst17
-rw-r--r--tests/data/common/sim_stderr_file0
-rw-r--r--tests/data/common/sim_stdout_file1
-rw-r--r--tests/data/common/ssh_stream_data1.txt3
-rw-r--r--tests/data/common/ssh_stream_data2.txt3
-rw-r--r--tests/data/common/ssh_stream_data3.txt3
-rw-r--r--tests/data/daisy_conf/daisy.conf2
-rw-r--r--tests/data/lab_conf/deploy_bare_odl-ha.yml43
-rw-r--r--tests/data/lab_conf/deploy_baremetal_invalid_ipmi.yml29
-rw-r--r--tests/data/lab_conf/deploy_vir1_nosdn-ha.yml32
-rw-r--r--tests/data/lab_conf/deploy_virtual_invalid_template.yml31
-rw-r--r--tests/unit/test_daisy_server.py324
-rw-r--r--tests/unit/test_deploy.py67
-rw-r--r--tests/unit/test_environment.py288
-rw-r--r--tests/unit/test_utils.py180
19 files changed, 951 insertions, 83 deletions
diff --git a/ci/build_rpm/build_rpms_docker.sh b/ci/build_rpm/build_rpms_docker.sh
index b005a243..c6d31f9a 100755
--- a/ci/build_rpm/build_rpms_docker.sh
+++ b/ci/build_rpm/build_rpms_docker.sh
@@ -62,4 +62,5 @@ cd ..
mv target/el7/noarch/installdaisy_el7_noarch.bin target/el7/noarch/opnfv-${OPNFV_ARTIFACT_VERSION}.bin
chmod +x target/el7/noarch/opnfv-${OPNFV_ARTIFACT_VERSION}.bin
cp target/el7/noarch/opnfv-${OPNFV_ARTIFACT_VERSION}.bin $rpm_output_dir
+mkisofs -o $rpm_output_dir/opnfv-${OPNFV_ARTIFACT_VERSION}.iso target/el7/noarch/
exit $rc
diff --git a/ci/deploy/deploy.sh b/ci/deploy/deploy.sh
index 208351d5..283dad1e 100755
--- a/ci/deploy/deploy.sh
+++ b/ci/deploy/deploy.sh
@@ -462,6 +462,10 @@ fi
echo "====== prepare cluster and pxe ======"
ssh $SSH_PARAS $DAISY_IP "python ${REMOTE_SPACE}/deploy/tempest.py --dha $DHA --network $NETWORK --cluster 'yes'"
+if [ $? -ne 0 ]; then
+ echo "Failed to prepare cluster and pxe, exit!"
+ exit 1
+fi
function get_mac_addresses_for_virtual()
@@ -549,6 +553,10 @@ fi
echo "====== prepare host and pxe ======"
ssh $SSH_PARAS $DAISY_IP "python ${REMOTE_SPACE}/deploy/tempest.py --dha $DHA --network $NETWORK --host 'yes' --isbare $IS_BARE --scenario $DEPLOY_SCENARIO"
+if [ $? -ne 0 ]; then
+ echo "Failed to prepare host and pxe, exit!"
+ exit 1
+fi
if [ $IS_BARE == 0 ];then
echo "====== daisy virtual-deploy operating system and openstack ======"
diff --git a/deploy/tempest.py b/deploy/tempest.py
index 916ebad5..89411f3f 100644
--- a/deploy/tempest.py
+++ b/deploy/tempest.py
@@ -138,6 +138,7 @@ def prepare_install():
except Exception:
print("Deploy failed!!!.%s." % traceback.format_exc())
+ sys.exit(1)
else:
print_bar("Everything is done!")
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 3418a128..0e643035 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -5,6 +5,7 @@ ENV BRANCH=${BRANCH:-master}
RUN yum -y update
RUN yum -y install centos-release-openstack-ocata
RUN yum -y install \
+ genisoimage \
wget \
coreutils \
which \
diff --git a/docs/release/installation/installation_guide.rst b/docs/release/installation/installation_guide.rst
index 7e72db42..3017f1cd 100644
--- a/docs/release/installation/installation_guide.rst
+++ b/docs/release/installation/installation_guide.rst
@@ -21,24 +21,27 @@ Before starting the installation of the Euphrates release of OPNFV, some plannin
must be done.
-Retrieve the installation bin image
+Retrieve the installation iso image
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-First of all, the installation bin which includes packages of Daisy, OS,
+First of all, the installation iso which includes packages of Daisy, OS,
OpenStack, and so on is needed for deploying your OPNFV environment.
-The stable release bin image can be retrieved via `OPNFV software download page <https://www.opnfv.org/software>`_
+The stable release iso image can be retrieved via `OPNFV software download page <https://www.opnfv.org/software>`_
-The daily build bin image can be retrieved via OPNFV artifact repository:
+The daily build iso image can be retrieved via OPNFV artifact repository:
http://artifacts.opnfv.org/daisy.html
-NOTE: Search the keyword "daisy/Euphrates" to locate the bin image.
+NOTE: Search the keyword "daisy/Euphrates" to locate the iso image.
E.g.
-daisy/opnfv-gerrit-27155.bin
+daisy/opnfv-2017-10-06_09-50-23.iso
-The git url and sha1 of bin image are recorded in properties files.
+Download the iso file, then mount it to a specified directory and get the
+opnfv-*.bin from that directory.
+
+The git url and sha512 checksum of iso image are recorded in properties files.
According to these, the corresponding deployment scripts can be retrieved.
diff --git a/tests/data/common/sim_stderr_file b/tests/data/common/sim_stderr_file
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tests/data/common/sim_stderr_file
diff --git a/tests/data/common/sim_stdout_file b/tests/data/common/sim_stdout_file
new file mode 100644
index 00000000..e1a1a8d2
--- /dev/null
+++ b/tests/data/common/sim_stdout_file
@@ -0,0 +1 @@
+stdout file data \ No newline at end of file
diff --git a/tests/data/common/ssh_stream_data1.txt b/tests/data/common/ssh_stream_data1.txt
new file mode 100644
index 00000000..0d9da1de
--- /dev/null
+++ b/tests/data/common/ssh_stream_data1.txt
@@ -0,0 +1,3 @@
+test_ssh_cmd1
+test_ssh_cmd2
+test_ssh_cmd3
diff --git a/tests/data/common/ssh_stream_data2.txt b/tests/data/common/ssh_stream_data2.txt
new file mode 100644
index 00000000..00ee55c3
--- /dev/null
+++ b/tests/data/common/ssh_stream_data2.txt
@@ -0,0 +1,3 @@
+test_ssh_cmd1
+test_ssh_cmd2
+test_ssh_cmd3 \ No newline at end of file
diff --git a/tests/data/common/ssh_stream_data3.txt b/tests/data/common/ssh_stream_data3.txt
new file mode 100644
index 00000000..289d65cb
--- /dev/null
+++ b/tests/data/common/ssh_stream_data3.txt
@@ -0,0 +1,3 @@
+test_ssh_cmd1
+test_ssh_cmd2
+test_ssh_cmd3 option1 \ No newline at end of file
diff --git a/tests/data/daisy_conf/daisy.conf b/tests/data/daisy_conf/daisy.conf
index 22e71d59..5435b4c0 100644
--- a/tests/data/daisy_conf/daisy.conf
+++ b/tests/data/daisy_conf/daisy.conf
@@ -1,7 +1,7 @@
[DEFAULT]
#The mangement ip of daisy
#When Daisy will be installed in the virtual machine, this option is required.
-daisy_management_ip=10.20.11.2
+
[BACKEND]
#Default backend types of daisy, including tecs, zenic, proton, kolla.
diff --git a/tests/data/lab_conf/deploy_bare_odl-ha.yml b/tests/data/lab_conf/deploy_bare_odl-ha.yml
new file mode 100644
index 00000000..28e8c195
--- /dev/null
+++ b/tests/data/lab_conf/deploy_bare_odl-ha.yml
@@ -0,0 +1,43 @@
+adapter: 'ipmi'
+hosts:
+- name: 'controller01'
+ roles:
+ - 'CONTROLLER_LB'
+ ipmi_ip: '192.168.1.11'
+ ipmi_user: 'testuser'
+ ipmi_pass: 'testpass'
+- name: 'controller02'
+ roles:
+ - 'CONTROLLER_LB'
+ ipmi_ip: '192.168.1.12'
+ ipmi_user: 'testuser'
+ ipmi_pass: 'testpass'
+- name: 'controller03'
+ roles:
+ - 'CONTROLLER_LB'
+ ipmi_ip: '192.168.1.13'
+ ipmi_user: 'testuser'
+ ipmi_pass: 'testpass'
+- name: 'computer01'
+ roles:
+ - 'COMPUTER'
+ ipmi_ip: '192.168.1.14'
+ ipmi_user: 'testuser'
+ ipmi_pass: 'testpass'
+- name: 'computer02'
+ roles:
+ - 'COMPUTER'
+ ipmi_ip: '192.168.1.15'
+ ipmi_user: 'testuser'
+ ipmi_pass: 'testpass'
+disks:
+ daisy: 50
+daisy_passwd: 'r00tme'
+daisy_ip: '10.20.0.2'
+daisy_gateway: '10.20.0.1'
+ceph_disk_name: '/dev/sdb'
+modules:
+ - module: opendaylight
+ module-config:
+ - enable_l3_odl:
+ value: true
diff --git a/tests/data/lab_conf/deploy_baremetal_invalid_ipmi.yml b/tests/data/lab_conf/deploy_baremetal_invalid_ipmi.yml
new file mode 100644
index 00000000..2e6de5a3
--- /dev/null
+++ b/tests/data/lab_conf/deploy_baremetal_invalid_ipmi.yml
@@ -0,0 +1,29 @@
+adapter: 'ipmi'
+hosts:
+- name: 'controller01'
+ roles:
+ - 'CONTROLLER_LB'
+- name: 'controller02'
+ roles:
+ - 'CONTROLLER_LB'
+- name: 'controller03'
+ roles:
+ - 'CONTROLLER_LB'
+- name: 'computer01'
+ roles:
+ - 'COMPUTER'
+ ipmi_ip: '192.168.1.14'
+ ipmi_user: 'testuser'
+ ipmi_pass: 'testpass'
+- name: 'computer02'
+ roles:
+ - 'COMPUTER'
+ ipmi_ip: '192.168.1.15'
+ ipmi_user: 'testuser'
+ ipmi_pass: 'testpass'
+disks:
+ daisy: 50
+daisy_passwd: 'r00tme'
+daisy_ip: '10.20.0.2'
+daisy_gateway: '10.20.0.1'
+ceph_disk_name: '/dev/sdb' \ No newline at end of file
diff --git a/tests/data/lab_conf/deploy_vir1_nosdn-ha.yml b/tests/data/lab_conf/deploy_vir1_nosdn-ha.yml
new file mode 100644
index 00000000..688b4f4f
--- /dev/null
+++ b/tests/data/lab_conf/deploy_vir1_nosdn-ha.yml
@@ -0,0 +1,32 @@
+adapter: libvirt
+hosts:
+- name: 'controller01'
+ roles:
+ - 'CONTROLLER_LB'
+ template: 'templates/virtual_environment/vms/controller.xml'
+- name: 'controller02'
+ roles:
+ - 'CONTROLLER_LB'
+ template: 'templates/virtual_environment/vms/controller.xml'
+- name: 'controller03'
+ roles:
+ - 'CONTROLLER_LB'
+ template: 'templates/virtual_environment/vms/controller.xml'
+- name: 'computer01'
+ roles:
+ - 'COMPUTER'
+ template: 'templates/virtual_environment/vms/computer.xml'
+- name: 'computer02'
+ roles:
+ - 'COMPUTER'
+ template: 'templates/virtual_environment/vms/computer.xml'
+disks:
+ daisy: 50
+ controller: 110
+ compute: 110
+ ceph: 110
+daisy_passwd: 'r00tme'
+daisy_ip: '10.20.11.2'
+daisy_gateway: '10.20.11.1'
+ceph_disk_name: '/dev/sdb'
+modules:
diff --git a/tests/data/lab_conf/deploy_virtual_invalid_template.yml b/tests/data/lab_conf/deploy_virtual_invalid_template.yml
new file mode 100644
index 00000000..483532cb
--- /dev/null
+++ b/tests/data/lab_conf/deploy_virtual_invalid_template.yml
@@ -0,0 +1,31 @@
+adapter: libvirt
+hosts:
+- name: 'controller01'
+ roles:
+ - 'CONTROLLER_LB'
+ template: 'controller.xml'
+- name: 'controller02'
+ roles:
+ - 'CONTROLLER_LB'
+ template: 'controller.xml'
+- name: 'controller03'
+ roles:
+ - 'CONTROLLER_LB'
+ template: 'controller.xml'
+- name: 'computer01'
+ roles:
+ - 'COMPUTER'
+ template: 'computer.xml'
+- name: 'computer02'
+ roles:
+ - 'COMPUTER'
+ template: 'computer.xml'
+disks:
+ daisy: 50
+ controller: 110
+ compute: 110
+ ceph: 110
+daisy_passwd: 'r00tme'
+daisy_ip: '10.20.11.2'
+daisy_gateway: '10.20.11.1'
+ceph_disk_name: '/dev/sdb' \ No newline at end of file
diff --git a/tests/unit/test_daisy_server.py b/tests/unit/test_daisy_server.py
index ada3c96d..97e0a1e2 100644
--- a/tests/unit/test_daisy_server.py
+++ b/tests/unit/test_daisy_server.py
@@ -1,18 +1,81 @@
import os
import pytest
import mock
+import paramiko
from deploy import daisy_server
from deploy.daisy_server import (
- DaisyServer
+ DaisyServer,
+ log_from_stream,
+ log_scp
)
+from deploy.utils import WORKSPACE
-@pytest.fixture(scope="session")
+@pytest.fixture(scope="module")
def conf_file_dir(data_root):
return os.path.join(data_root, 'lab_conf')
+@pytest.fixture(scope="module")
+def common_test_file_dir(data_root):
+ return os.path.join(data_root, 'common')
+
+
+def ssh_test_file_dir():
+ return os.path.join(WORKSPACE, 'tests/data/common')
+
+
+def get_ssh_test_command_from_file(dir, file_name):
+ file_path = os.path.join(dir, file_name)
+ with open(file_path) as f:
+ return f.read()
+
+
+data1 = get_ssh_test_command_from_file(ssh_test_file_dir(), 'ssh_stream_data1.txt')
+res1 = None
+expected_ret1 = None
+res2 = 'test_res_commd'
+data2 = get_ssh_test_command_from_file(ssh_test_file_dir(), 'ssh_stream_data2.txt')
+expected_ret2 = 'test_ssh_cmd3'
+data3 = get_ssh_test_command_from_file(ssh_test_file_dir(), 'ssh_stream_data3.txt')
+
+
+@pytest.mark.parametrize('data, res, expected', [
+ (data1, res1, expected_ret1),
+ (data1, res2, expected_ret1),
+ (data2, res1, expected_ret2),
+ (data2, res2, expected_ret2),
+ (data3, res1, expected_ret1),
+ (data3, res2, expected_ret1)])
+def test_log_from_stream(data, res, expected):
+ def log_func(str):
+ print str
+ pre_val = daisy_server.BLOCK_SIZE
+ daisy_server.BLOCK_SIZE = 16
+ ret = log_from_stream(res, data, log_func)
+ daisy_server.BLOCK_SIZE = pre_val
+ assert expected == ret
+
+
+@pytest.mark.parametrize('filename, size, send', [
+ ('test_file_name', 1024, 1000),
+ ('test_file_name', 2048, 2048),
+ ('test_file_name_1234', 2097152, 2097152)])
+@mock.patch('deploy.daisy_server.LD')
+def test_log_scp(mock_LD, filename, size, send):
+ pre_val = daisy_server.LEN_OF_NAME_PART
+ daisy_server.LEN_OF_NAME_PART = 24
+ log_scp(filename, size, send)
+ daisy_server.LEN_OF_NAME_PART = pre_val
+ if size != send:
+ mock_LD.assert_not_called()
+ elif len(filename) <= 18:
+ mock_LD.assert_called_once()
+ else:
+ assert mock_LD.call_count == 2
+
+
daisy_server_info = {
'name': 'daisy',
'image': 'daisy.qcow2',
@@ -53,6 +116,239 @@ def test_create_DaisyServer_instance(tmpdir):
tmpdir.remove()
+@mock.patch.object(daisy_server.paramiko.SSHClient, 'connect')
+@mock.patch.object(daisy_server.DaisyServer, 'ssh_run')
+def test_connect_DaisyServer(mock_ssh_run, mock_connect, tmpdir):
+ bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name)
+ mock_connect.return_value = 0
+ DaisyServerInst = DaisyServer(daisy_server_info['name'],
+ daisy_server_info['address'],
+ daisy_server_info['password'],
+ remote_dir,
+ bin_file,
+ adapter,
+ scenario,
+ deploy_file_name,
+ net_file_name)
+ DaisyServerInst.connect()
+ mock_ssh_run.assert_called_once_with('ls -al', check=True)
+ tmpdir.remove()
+
+
+@mock.patch.object(daisy_server.paramiko.SSHClient, 'close')
+@mock.patch.object(daisy_server.paramiko.SSHClient, 'connect')
+@mock.patch.object(daisy_server.DaisyServer, 'ssh_run')
+def test_close_DaisyServer(mock_ssh_run, mock_connect,
+ mock_close, tmpdir):
+ bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name)
+ mock_connect.return_value = 0
+ mock_ssh_run.return_valule = 0
+ mock_close.return_value = 0
+ DaisyServerInst = DaisyServer(daisy_server_info['name'],
+ daisy_server_info['address'],
+ daisy_server_info['password'],
+ remote_dir,
+ bin_file,
+ adapter,
+ scenario,
+ deploy_file_name,
+ net_file_name)
+ DaisyServerInst.connect()
+ DaisyServerInst.close()
+ mock_close.assert_called_once_with()
+ tmpdir.remove()
+
+
+stdout1 = open(os.path.join(ssh_test_file_dir(), 'sim_stdout_file'))
+stdin1 = open(os.path.join(ssh_test_file_dir(), 'sim_stdout_file'))
+stderr1 = open(os.path.join(ssh_test_file_dir(), 'sim_stderr_file'))
+stderr2 = open(os.path.join(ssh_test_file_dir(), 'sim_stdout_file'))
+
+
+@pytest.mark.parametrize('stdout, stdin, stderr', [
+ (stdout1, stdin1, stderr1),
+ (stdout1, stdin1, stderr2)])
+@mock.patch('deploy.daisy_server.err_exit')
+@mock.patch.object(daisy_server.paramiko.SSHClient, 'connect')
+@mock.patch.object(daisy_server.paramiko.SSHClient, 'exec_command')
+@mock.patch.object(daisy_server.DaisyServer, 'ssh_run')
+def test_ssh_exec_cmd_DaisyServer(mock_ssh_run, mock_exec_command,
+ mock_connect, mock_err_exit,
+ stdout, stdin, stderr, tmpdir):
+ bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name)
+ cmd = 'ls -l'
+ mock_connect.return_value = 0
+ mock_ssh_run.return_valule = 0
+ expect = 'stdout file data'
+ mock_exec_command.return_value = (stdin, stdout, stderr)
+ DaisyServerInst = DaisyServer(daisy_server_info['name'],
+ daisy_server_info['address'],
+ daisy_server_info['password'],
+ remote_dir,
+ bin_file,
+ adapter,
+ scenario,
+ deploy_file_name,
+ net_file_name)
+ DaisyServerInst.connect()
+ ret = DaisyServerInst.ssh_exec_cmd(cmd)
+ mock_exec_command.assert_called_once()
+ if stderr == stderr1:
+ if stdout == stdout1:
+ assert ret == expect
+ elif stderr == stderr2:
+ mock_err_exit.assert_called_once_with('SSH client error occurred')
+ tmpdir.remove()
+
+
+@pytest.mark.parametrize('check, is_recv_exit_status, expect', [
+ (False, 0, 0),
+ (True, 1, 1)])
+@mock.patch('deploy.daisy_server.err_exit')
+@mock.patch.object(daisy_server.paramiko.SSHClient, 'get_transport')
+def test_ssh_run_DaisyServer(mock_get_transport, mock_err_exit,
+ check, is_recv_exit_status,
+ expect, tmpdir):
+ class TestSession():
+
+ def __init__(self, is_recv_exit_status):
+ self.recv_data = 'recv_test_data'
+ self.recv_data_total_len = len(self.recv_data)
+ self.recv_data_read_index = 0
+ self.recv_err_data = 'recv_test_err_data'
+ self.recv_err_data_total_len = len(self.recv_err_data)
+ self.recv_err_data_read_index = 0
+ self.is_recv_exit_status = is_recv_exit_status
+ return None
+
+ def exec_command(self, cmd):
+ return 0
+
+ def recv_ready(self):
+ return True
+
+ def recv(self, size):
+ if self.recv_data_read_index < self.recv_data_total_len:
+ if size <= self.recv_data_total_len - self.recv_data_read_index:
+ cur_index = self.recv_data_read_index
+ self.recv_data_read_index += size
+ return self.recv_data[cur_index:self.recv_data_read_index]
+ else:
+ cur_index = self.recv_data_read_index
+ self.recv_data_read_index = self.recv_data_total_len
+ return self.recv_data[cur_index:]
+ else:
+ return None
+
+ def recv_stderr_ready(self):
+ return True
+
+ def recv_stderr(self, size):
+ if self.recv_err_data_read_index < self.recv_err_data_total_len:
+ if size <= self.recv_err_data_total_len - self.recv_err_data_read_index:
+ cur_index = self.recv_err_data_read_index
+ self.recv_err_data_read_index += size
+ return self.recv_err_data[cur_index:self.recv_err_data_read_index]
+ else:
+ cur_index = self.recv_err_data_read_index
+ self.recv_err_data_read_index = self.recv_err_data_total_len
+ return self.recv_err_data[cur_index:]
+ else:
+ return None
+
+ def exit_status_ready(self):
+ return True
+
+ def recv_exit_status(self):
+ return self.is_recv_exit_status
+
+ class TestTransport():
+ def __init__(self, is_recv_exit_status):
+ self.is_recv_exit_status = is_recv_exit_status
+
+ def set_keepalive(self, time):
+ self.time = time
+
+ def open_session(self):
+ return TestSession(is_recv_exit_status)
+
+ bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name)
+ cmd = 'ls -l'
+ mock_get_transport.return_value = TestTransport(is_recv_exit_status)
+ DaisyServerInst = DaisyServer(daisy_server_info['name'],
+ daisy_server_info['address'],
+ daisy_server_info['password'],
+ remote_dir,
+ bin_file,
+ adapter,
+ scenario,
+ deploy_file_name,
+ net_file_name)
+ DaisyServerInst.ssh_client = paramiko.SSHClient()
+ DaisyServerInst.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ ret = DaisyServerInst.ssh_run(cmd, check=check)
+ if check and is_recv_exit_status:
+ mock_err_exit.assert_called_once()
+ assert ret == expect
+ tmpdir.remove()
+
+
+@mock.patch.object(daisy_server.scp.SCPClient, 'get')
+@mock.patch.object(daisy_server.paramiko.SSHClient, 'get_transport')
+@mock.patch.object(daisy_server.paramiko.SSHClient, 'connect')
+@mock.patch.object(daisy_server.paramiko.SSHClient, 'exec_command')
+@mock.patch.object(daisy_server.DaisyServer, 'ssh_run')
+def test_scp_get_DaisyServer(mock_ssh_run, mock_exec_command,
+ mock_connect, mock_get_transport,
+ mock_get, tmpdir):
+ bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name)
+ mock_connect.return_value = 0
+ mock_ssh_run.return_valule = 0
+ remote = '/remote_dir'
+ local = '.'
+ DaisyServerInst = DaisyServer(daisy_server_info['name'],
+ daisy_server_info['address'],
+ daisy_server_info['password'],
+ remote_dir,
+ bin_file,
+ adapter,
+ scenario,
+ deploy_file_name,
+ net_file_name)
+ DaisyServerInst.connect()
+ DaisyServerInst.scp_get(remote, local)
+ mock_get.assert_called_once_with(remote, local_path=local, recursive=True)
+ tmpdir.remove()
+
+
+@mock.patch.object(daisy_server.scp.SCPClient, 'put')
+@mock.patch.object(daisy_server.paramiko.SSHClient, 'get_transport')
+@mock.patch.object(daisy_server.paramiko.SSHClient, 'connect')
+@mock.patch.object(daisy_server.paramiko.SSHClient, 'exec_command')
+@mock.patch.object(daisy_server.DaisyServer, 'ssh_run')
+def test_scp_put_DaisyServer(mock_ssh_run, mock_exec_command,
+ mock_connect, mock_get_transport,
+ mock_put, tmpdir):
+ bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name)
+ mock_connect.return_value = 0
+ mock_ssh_run.return_valule = 0
+ remote = '.'
+ local = '/tmp'
+ DaisyServerInst = DaisyServer(daisy_server_info['name'],
+ daisy_server_info['address'],
+ daisy_server_info['password'],
+ remote_dir,
+ bin_file,
+ adapter,
+ scenario,
+ deploy_file_name,
+ net_file_name)
+ DaisyServerInst.connect()
+ DaisyServerInst.scp_put(local, remote)
+ mock_put.assert_called_once_with(local, remote_path=remote, recursive=True)
+ tmpdir.remove()
+
+
@mock.patch.object(daisy_server.DaisyServer, 'ssh_exec_cmd')
def test_create_dir_DaisyServer(mock_ssh_exec_cmd, tmpdir):
remote_dir_test = '/home/daisy/test'
@@ -91,6 +387,13 @@ def test_delete_dir_DaisyServer(mock_ssh_exec_cmd, tmpdir):
tmpdir.remove()
+bin_file_path1 = os.path.join('/tmp', bin_file_name)
+bin_file_path2 = os.path.join(WORKSPACE, bin_file_name)
+
+
+@pytest.mark.parametrize('bin_file', [
+ (bin_file_path1),
+ (bin_file_path2)])
@mock.patch.object(daisy_server.DaisyServer, 'delete_dir')
@mock.patch.object(daisy_server.DaisyServer, 'scp_put')
@mock.patch.object(daisy_server.DaisyServer, 'create_dir')
@@ -99,8 +402,8 @@ def test_prepare_files_DaisyServer(mock_update_config,
mock_create_dir,
mock_scp_put,
mock_delete_dir,
+ bin_file,
tmpdir):
- bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name)
DaisyServerInst = DaisyServer(daisy_server_info['name'],
daisy_server_info['address'],
daisy_server_info['password'],
@@ -113,7 +416,10 @@ def test_prepare_files_DaisyServer(mock_update_config,
DaisyServerInst.prepare_files()
DaisyServerInst.delete_dir.assert_called_once_with(remote_dir)
DaisyServerInst.create_dir.assert_called_once_with('/home/daisy_install')
- assert DaisyServerInst.scp_put.call_count == 3
+ if bin_file == bin_file_path1:
+ assert DaisyServerInst.scp_put.call_count == 3
+ else:
+ assert DaisyServerInst.scp_put.call_count == 2
tmpdir.remove()
@@ -138,10 +444,11 @@ def test_install_daisy_DaisyServer(mock_prepare_files, mock_ssh_run, tmpdir):
tmpdir.remove()
+@pytest.mark.parametrize('adapter', [
+ ('libvirt'), ('ipmi')])
@mock.patch.object(daisy_server.DaisyServer, 'ssh_run')
-def test_prepare_configurations_DaisyServer(mock_ssh_run, tmpdir):
+def test_prepare_configurations_DaisyServer(mock_ssh_run, adapter, tmpdir):
bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, bin_file_name)
- adapter = 'libvirt'
DaisyServerInst = DaisyServer(daisy_server_info['name'],
daisy_server_info['address'],
daisy_server_info['password'],
@@ -158,7 +465,10 @@ def test_prepare_configurations_DaisyServer(mock_ssh_run, tmpdir):
net_file=os.path.join(remote_dir, net_file_name),
is_bare=1 if adapter == 'ipmi' else 0)
DaisyServerInst.prepare_configurations()
- DaisyServerInst.ssh_run.assert_called_once_with(cmd)
+ if adapter == 'libvirt':
+ DaisyServerInst.ssh_run.assert_called_once_with(cmd)
+ else:
+ DaisyServerInst.ssh_run.assert_not_called()
tmpdir.remove()
diff --git a/tests/unit/test_deploy.py b/tests/unit/test_deploy.py
index 0c4ebb6f..142a7f45 100644
--- a/tests/unit/test_deploy.py
+++ b/tests/unit/test_deploy.py
@@ -16,7 +16,7 @@ from deploy.utils import WORKSPACE
import mock
sys.modules['libvirt'] = mock.Mock()
-from deploy import environment # noqa: ignore=E402
+from deploy import environment # noqa: ignore=E402
from deploy.deploy import (
config_arg_parser,
DaisyDeployment,
@@ -128,6 +128,66 @@ def test_create_DaisyDeployment_instance(mock_err_exit, mock_deploy_schema_valid
tmpdir.remove()
+@pytest.mark.parametrize('kwargs, is_use_pdf, exp_deploy_file', [
+ (
+ {
+ 'lab_name': 'zte',
+ 'pod_name': 'virtual1',
+ 'deploy_file': 'deploy_virtual1.yml',
+ 'net_file': 'network_virtual1.yml',
+ 'bin_file': 'opnfv.bin',
+ 'daisy_only': False,
+ 'cleanup_only': False,
+ 'remote_dir': '/home/daisy',
+ 'work_dir': 'workdir',
+ 'storage_dir': 'vms',
+ 'pxe_bridge': 'libvirt',
+ 'deploy_log': 'deploy.log',
+ 'scenario': 'os-nosdn-nofeature-ha'
+ }, False, 'deploy_vir1_nosdn-ha.yml'
+ ),
+ (
+ {
+ 'lab_name': 'zte',
+ 'pod_name': 'pod1',
+ 'deploy_file': 'deploy_baremetal.yml',
+ 'net_file': 'network_baremetal.yml',
+ 'bin_file': 'opnfv.bin',
+ 'daisy_only': False,
+ 'cleanup_only': False,
+ 'remote_dir': '/home/daisy',
+ 'work_dir': 'workdir',
+ 'storage_dir': 'vms',
+ 'pxe_bridge': 'pxebr',
+ 'deploy_log': 'deploy.log',
+ 'scenario': 'os-odl-nofeature-ha'
+ }, True, 'deploy_bare_odl-ha.yml'
+ )])
+@mock.patch.object(DaisyDeployment, '_use_pod_descriptor_file')
+def test__construct_final_deploy_conf_in_DaisyDeployment(mock__use_pod_descriptor_file,
+ conf_file_dir, tmpdir,
+ kwargs, is_use_pdf, exp_deploy_file):
+ kwargs['deploy_file'] = os.path.join(conf_file_dir, kwargs['deploy_file'])
+ kwargs['net_file'] = os.path.join(conf_file_dir, kwargs['net_file'])
+ tmpdir.join(kwargs['bin_file']).write('testdata')
+ kwargs['bin_file'] = os.path.join(tmpdir.dirname, tmpdir.basename, kwargs['bin_file'])
+ kwargs['deploy_log'] = os.path.join(tmpdir.dirname, tmpdir.basename, kwargs['deploy_log'])
+ tmpsubdir = tmpdir.mkdir(kwargs['work_dir'])
+ kwargs['work_dir'] = os.path.join(tmpsubdir.dirname, tmpsubdir.basename)
+ tmpsubdir = tmpdir.mkdir(kwargs['storage_dir'])
+ kwargs['storage_dir'] = os.path.join(tmpsubdir.dirname, tmpsubdir.basename)
+ exp_deploy_file_path = os.path.join(conf_file_dir, exp_deploy_file)
+ pdf_deploy_file = None if not is_use_pdf else kwargs['deploy_file']
+
+ mock__use_pod_descriptor_file.return_value = pdf_deploy_file
+ daisy_deploy = DaisyDeployment(**kwargs)
+ mock__use_pod_descriptor_file.asser_called_once_with()
+ with open(exp_deploy_file_path) as yaml_file:
+ exp_deploy_struct = yaml.safe_load(yaml_file)
+ assert daisy_deploy.deploy_struct == exp_deploy_struct
+ tmpdir.remove()
+
+
@pytest.mark.parametrize('kwargs', [
(
{
@@ -213,6 +273,8 @@ def test_run_in_DaisyDeployment(mock_deploy, mock_install_daisy,
tmpdir.remove()
+@pytest.mark.parametrize('cleanup_only', [
+ (False), (True)])
@mock.patch('deploy.deploy.argparse.ArgumentParser.parse_args')
@mock.patch('deploy.deploy.check_sudo_privilege')
@mock.patch('deploy.deploy.save_log_to_file')
@@ -223,7 +285,7 @@ def test_run_in_DaisyDeployment(mock_deploy, mock_install_daisy,
def test_parse_arguments(mock_confirm_dir_exists, mock_make_file_executable,
mock_check_file_exists, mock_check_scenario_valid,
mock_save_log_to_file, mock_check_sudo_privilege,
- mock_parse_args, tmpdir):
+ mock_parse_args, cleanup_only, tmpdir):
class MockArg():
def __init__(self, lab_name, pod_name, bin_file, daisy_only,
cleanup_only, remote_dir, work_dir, storage_dir, pxe_bridge,
@@ -245,7 +307,6 @@ def test_parse_arguments(mock_confirm_dir_exists, mock_make_file_executable,
conf_base_dir = os.path.join(WORKSPACE, 'labs', 'zte', 'pod2')
deploy_file = os.path.join(conf_base_dir, 'daisy/config/deploy.yml')
net_file = os.path.join(conf_base_dir, 'daisy/config/network.yml')
- cleanup_only = False
expected = {
'lab_name': 'zte',
'pod_name': 'pod2',
diff --git a/tests/unit/test_environment.py b/tests/unit/test_environment.py
index 250a80a9..dcd8b046 100644
--- a/tests/unit/test_environment.py
+++ b/tests/unit/test_environment.py
@@ -2,10 +2,13 @@ import os
import copy
import mock
import yaml
+import pytest
from deepdiff import DeepDiff
from deploy.utils import WORKSPACE
from deploy import environment
+from deploy import daisy_server
+from deploy.daisy_server import DaisyServer
from deploy.environment import (
DaisyEnvironmentBase,
BareMetalEnvironment,
@@ -29,6 +32,7 @@ def get_conf_info_from_file(file_dir, conf_file_name):
deploy_struct = get_conf_info_from_file(get_conf_file_dir(), 'deploy_baremetal.yml')
deploy_virtual_struct = get_conf_info_from_file(get_conf_file_dir(), 'deploy_virtual1.yml')
+deploy_virtual2_struct = get_conf_info_from_file(get_conf_file_dir(), 'deploy_virtual2.yml')
net_struct = get_conf_info_from_file(get_conf_file_dir(), 'network_baremetal.yml')
adapter = 'ipmi'
adapter_virtual = 'libvirt'
@@ -80,7 +84,18 @@ def test_delete_daisy_server_DaisyEnvironmentBase(tmpdir, mocker):
tmpdir.remove()
-def test_create_daisy_server_image_DaisyEnvironmentBase(tmpdir, monkeypatch):
+@pytest.mark.parametrize('ret_run_shell, ret_access', [
+ (0, 1),
+ (1, 0)])
+@mock.patch('deploy.environment.os.access')
+@mock.patch('deploy.environment.os.remove')
+@mock.patch('deploy.environment.shutil.move')
+@mock.patch('deploy.environment.err_exit')
+@mock.patch('deploy.environment.run_shell')
+def test_create_daisy_server_image_DaisyEnvironmentBase(mock_run_shell, mock_err_exit,
+ mock_move, mock_remove,
+ mock_access, tmpdir,
+ ret_run_shell, ret_access):
work_dir = os.path.join(tmpdir.dirname, tmpdir.basename, work_dir_name)
os.makedirs(work_dir, 0755)
storage_dir = os.path.join(tmpdir.dirname, tmpdir.basename, storage_dir_name)
@@ -90,15 +105,40 @@ def test_create_daisy_server_image_DaisyEnvironmentBase(tmpdir, monkeypatch):
DaisyEnvBaseInst = DaisyEnvironmentBase(
deploy_struct, net_struct, adapter, pxe_bridge,
daisy_server, work_dir, storage_dir, scenario)
+ mock_run_shell.return_value = ret_run_shell
+ mock_access.return_value = ret_access
+ mock_err_exit.return_value = 0
- def create_server_image_sucess(cmd):
- os.makedirs(os.path.join(work_dir, 'daisy'))
- with open(os.path.join(work_dir, 'daisy', 'centos7.qcow2'), 'w') as f:
- f.write('image-data')
- return 0
- monkeypatch.setattr(environment, 'run_shell', create_server_image_sucess)
DaisyEnvBaseInst.create_daisy_server_image()
- assert os.path.isfile(DaisyEnvBaseInst.daisy_server_info['image'])
+ if ret_run_shell:
+ mock_err_exit.assert_called_once_with('Failed to create Daisy Server image')
+ else:
+ if ret_access:
+ mock_remove.assert_called_once_with(DaisyEnvBaseInst.daisy_server_info['image'])
+ else:
+ mock_move.assert_called_once()
+ tmpdir.remove()
+
+
+@mock.patch.object(daisy_server.DaisyServer, 'connect')
+@mock.patch.object(daisy_server.DaisyServer, 'install_daisy')
+def test_install_daisy_DaisyEnvironmentBase(mock_install_daisy, mock_connect, tmpdir):
+ work_dir = os.path.join(tmpdir.dirname, tmpdir.basename, work_dir_name)
+ os.makedirs(work_dir, 0755)
+ storage_dir = os.path.join(tmpdir.dirname, tmpdir.basename, storage_dir_name)
+ os.makedirs(storage_dir, 0755)
+ daisy_server = copy.deepcopy(daisy_server_info)
+ daisy_server['image'] = os.path.join(storage_dir, daisy_server['image'])
+ remote_dir = '/home/daisy'
+ bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, 'opnfv.bin')
+ deploy_file_name = 'final_deploy.yml'
+ net_file_name = 'network_baremetal.yml'
+ 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)
+ mock_install_daisy.assert_called_once_with()
+ mock_connect.assert_called_once_with()
tmpdir.remove()
@@ -153,18 +193,36 @@ def test_create_daisy_server_vm_BareMetalEnvironment(mocker, tmpdir):
tmpdir.remove()
+@pytest.mark.parametrize('deploy_struct_info', [
+ (deploy_struct)])
@mock.patch('deploy.environment.ipmi_reboot_node')
-def test_reboot_nodes_BareMetalEnvironment(mock_ipmi_reboot_node, tmpdir):
+def test_reboot_nodes_BareMetalEnvironment(mock_ipmi_reboot_node,
+ deploy_struct_info, tmpdir):
work_dir = os.path.join(tmpdir.dirname, tmpdir.basename, work_dir_name)
storage_dir = os.path.join(tmpdir.dirname, tmpdir.basename, storage_dir_name)
daisy_server = copy.deepcopy(daisy_server_info)
daisy_server['image'] = os.path.join(storage_dir, daisy_server['image'])
mock_ipmi_reboot_node.return_value = True
BareMetalEnvironmentInst = BareMetalEnvironment(
- deploy_struct, net_struct, adapter, pxe_bridge,
+ deploy_struct_info, net_struct, adapter, pxe_bridge,
daisy_server, work_dir, storage_dir, scenario)
BareMetalEnvironmentInst.reboot_nodes()
- assert environment.ipmi_reboot_node.call_count == 5
+ assert mock_ipmi_reboot_node.call_count == 5
+ tmpdir.remove()
+
+
+@pytest.mark.parametrize('deploy_struct_info', [
+ (deploy_virtual_struct)])
+def test_reboot_nodes_err_BareMetalEnvironment(deploy_struct_info, tmpdir):
+ work_dir = os.path.join(tmpdir.dirname, tmpdir.basename, work_dir_name)
+ storage_dir = os.path.join(tmpdir.dirname, tmpdir.basename, storage_dir_name)
+ daisy_server = copy.deepcopy(daisy_server_info)
+ daisy_server['image'] = os.path.join(storage_dir, daisy_server['image'])
+ BareMetalEnvironmentInst = BareMetalEnvironment(
+ deploy_struct_info, net_struct, adapter, pxe_bridge,
+ daisy_server, work_dir, storage_dir, scenario)
+ with pytest.raises(SystemExit):
+ BareMetalEnvironmentInst.reboot_nodes()
tmpdir.remove()
@@ -186,6 +244,49 @@ def test_create_daisy_server_BareMetalEnvironment(mock_create_daisy_server_vm, m
tmpdir.remove()
+@mock.patch.object(daisy_server.DaisyServer, 'prepare_cluster')
+@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')
+@mock.patch.object(daisy_server.DaisyServer, 'check_openstack_installation')
+@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,
+ tmpdir):
+ work_dir = os.path.join(tmpdir.dirname, tmpdir.basename, work_dir_name)
+ storage_dir = os.path.join(tmpdir.dirname, tmpdir.basename, storage_dir_name)
+ daisy_server = copy.deepcopy(daisy_server_info)
+ daisy_server['image'] = os.path.join(storage_dir, daisy_server['image'])
+ deploy_file = os.path.join(get_conf_file_dir(), 'deploy_baremetal.yml')
+ net_file = os.path.join(get_conf_file_dir(), 'network_baremetal.yml')
+ remote_dir = '/home/daisy'
+ bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, 'opnfv.bin')
+ deploy_file_name = 'final_deploy.yml'
+ net_file_name = 'network_baremetal.yml'
+ BareMetalEnvironmentInst = BareMetalEnvironment(
+ deploy_struct, net_struct, adapter, pxe_bridge,
+ daisy_server, work_dir, storage_dir, scenario)
+ BareMetalEnvironmentInst.server = DaisyServer(
+ daisy_server['name'],
+ daisy_server['address'],
+ daisy_server['password'],
+ remote_dir,
+ bin_file,
+ adapter,
+ scenario,
+ deploy_file_name,
+ net_file_name)
+ BareMetalEnvironmentInst.deploy(deploy_file, net_file)
+ mock_prepare_cluster.assert_called_once_with(deploy_file, net_file)
+ 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']))
+ mock_check_openstack_installation.assert_called_once_with(len(BareMetalEnvironmentInst.deploy_struct['hosts']))
+ mock_post_deploy.assert_called_once_with()
+ tmpdir.remove()
+
+
def test_create_VirtualEnvironment_instance(tmpdir):
work_dir = os.path.join(tmpdir.dirname, tmpdir.basename, work_dir_name)
storage_dir = os.path.join(tmpdir.dirname, tmpdir.basename, storage_dir_name)
@@ -208,19 +309,67 @@ def test_create_VirtualEnvironment_instance(tmpdir):
tmpdir.remove()
+@mock.patch.object(environment.VirtualEnvironment, 'check_nodes_template')
+def test_check_configuration_VirtualEnvironment(mock_check_nodes_template, tmpdir):
+ work_dir = os.path.join(tmpdir.dirname, tmpdir.basename, work_dir_name)
+ storage_dir = os.path.join(tmpdir.dirname, tmpdir.basename, storage_dir_name)
+ daisy_server = copy.deepcopy(daisy_server_info)
+ daisy_server['image'] = os.path.join(storage_dir, daisy_server['image'])
+ VirtualEnvironment(
+ deploy_virtual_struct, net_struct, adapter_virtual, pxe_bridge_virtual,
+ daisy_server, work_dir, storage_dir, scenario)
+ mock_check_nodes_template.assert_called_once_with()
+ tmpdir.remove()
+
+
+deploy_virtual_invalid_struct = get_conf_info_from_file(get_conf_file_dir(), 'deploy_virtual_invalid_template.yml')
+
+
+@pytest.mark.parametrize('deploy_struct_info', [
+ (deploy_struct),
+ (deploy_virtual_struct),
+ (deploy_virtual_invalid_struct)])
+@mock.patch('deploy.environment.err_exit')
+def test_check_nodes_template_VirtualEnvironment(mock_err_exit, deploy_struct_info, tmpdir):
+ work_dir = os.path.join(tmpdir.dirname, tmpdir.basename, work_dir_name)
+ storage_dir = os.path.join(tmpdir.dirname, tmpdir.basename, storage_dir_name)
+ daisy_server = copy.deepcopy(daisy_server_info)
+ daisy_server['image'] = os.path.join(storage_dir, daisy_server['image'])
+ mock_err_exit.return_value = 0
+ VirtualEnvironment(
+ deploy_struct_info, net_struct, adapter_virtual, pxe_bridge_virtual,
+ daisy_server, work_dir, storage_dir, scenario)
+ if deploy_struct_info == deploy_struct:
+ mock_err_exit.assert_not_called()
+ elif deploy_struct_info == deploy_virtual_struct:
+ mock_err_exit.assert_not_called()
+ elif deploy_struct_info == deploy_virtual_invalid_struct:
+ assert mock_err_exit.call_count == 5
+ tmpdir.remove()
+
+
+@pytest.mark.parametrize('net_name', [
+ (pxe_bridge_virtual)])
@mock.patch('deploy.environment.create_virtual_network')
-def test_create_daisy_server_network_VirtualEnvironment(mock_create_virtual_network, tmpdir):
+@mock.patch('deploy.environment.err_exit')
+def test_create_daisy_server_network_VirtualEnvironment(mock_err_exit, mock_create_virtual_network,
+ net_name, tmpdir):
work_dir = os.path.join(tmpdir.dirname, tmpdir.basename, work_dir_name)
storage_dir = os.path.join(tmpdir.dirname, tmpdir.basename, storage_dir_name)
daisy_server = copy.deepcopy(daisy_server_info)
daisy_server['image'] = os.path.join(storage_dir, daisy_server['image'])
- mock_create_virtual_network.return_value = pxe_bridge_virtual
+ mock_create_virtual_network.return_value = net_name
+ mock_err_exit.return_value = 0
VirtualEnvironmentInst = VirtualEnvironment(
deploy_virtual_struct, net_struct, adapter_virtual, pxe_bridge_virtual,
daisy_server, work_dir, storage_dir, scenario)
VirtualEnvironmentInst.create_daisy_server_network()
- environment.create_virtual_network.assert_called_once_with(VMDEPLOY_DAISY_SERVER_NET)
- assert VirtualEnvironmentInst._daisy_server_net == pxe_bridge_virtual
+ mock_create_virtual_network.assert_called_once_with(VMDEPLOY_DAISY_SERVER_NET)
+ if net_name == pxe_bridge_virtual:
+ mock_err_exit.assert_not_called()
+ assert VirtualEnvironmentInst._daisy_server_net == pxe_bridge_virtual
+ elif net_name == pxe_bridge:
+ mock_err_exit.assert_called_once()
tmpdir.remove()
@@ -238,6 +387,7 @@ def test_create_daisy_server_vm_VirtualEnvironment(mock_create_vm, tmpdir):
environment.create_vm.assert_called_once_with(VMDEPLOY_DAISY_SERVER_VM,
name=daisy_server['name'],
disks=[daisy_server['image']])
+ tmpdir.remove()
@mock.patch.object(environment.DaisyEnvironmentBase, 'create_daisy_server_image')
@@ -261,23 +411,30 @@ def test_create_daisy_server_VirtualEnvironment(mock_create_daisy_server_vm,
tmpdir.remove()
+@pytest.mark.parametrize('deploy_info_struct, node_num', [
+ (deploy_virtual_struct, 0),
+ (deploy_virtual_struct, 3),
+ (deploy_virtual2_struct, 0)])
@mock.patch('deploy.environment.create_vm')
@mock.patch('deploy.environment.create_virtual_disk')
-def test_create_virtual_node_VirtualEnvironment(mock_create_virtual_disk,
- mock_create_vm,
- tmpdir):
+def test_create_virtual_node_VirtualEnvironment(mock_create_virtual_disk, mock_create_vm,
+ deploy_info_struct, node_num, tmpdir):
work_dir = os.path.join(tmpdir.dirname, tmpdir.basename, work_dir_name)
storage_dir = os.path.join(tmpdir.dirname, tmpdir.basename, storage_dir_name)
daisy_server = copy.deepcopy(daisy_server_info)
daisy_server['image'] = os.path.join(storage_dir, daisy_server['image'])
VirtualEnvironmentInst = VirtualEnvironment(
- deploy_virtual_struct, net_struct, adapter_virtual, pxe_bridge_virtual,
+ deploy_info_struct, net_struct, adapter_virtual, pxe_bridge_virtual,
daisy_server, work_dir, storage_dir, scenario)
- VirtualEnvironmentInst.create_virtual_node(deploy_virtual_struct['hosts'][0])
- environment.create_virtual_disk.call_count == 2
- name = deploy_virtual_struct['hosts'][0]['name']
- template = deploy_virtual_struct['hosts'][0]['template']
- files = [os.path.join(storage_dir, name + '.qcow2'), os.path.join(storage_dir, name + '_data.qcow2')]
+ VirtualEnvironmentInst.create_virtual_node(deploy_info_struct['hosts'][node_num])
+ name = deploy_info_struct['hosts'][node_num]['name']
+ template = deploy_info_struct['hosts'][node_num]['template']
+ if deploy_info_struct == deploy_virtual_struct:
+ files = [os.path.join(storage_dir, name + '.qcow2'), os.path.join(storage_dir, name + '_data.qcow2')]
+ assert environment.create_virtual_disk.call_count == 2
+ elif deploy_info_struct == deploy_virtual2_struct:
+ files = [os.path.join(storage_dir, name + '.qcow2')]
+ assert environment.create_virtual_disk.call_count == 1
environment.create_vm.assert_called_once_with(template, name, files)
tmpdir.remove()
@@ -321,6 +478,7 @@ def test_delete_nodes_VirtualEnvironment(mock_delete_vm_and_disk, tmpdir):
daisy_server, work_dir, storage_dir, scenario)
VirtualEnvironmentInst.delete_nodes()
assert environment.delete_vm_and_disk.call_count == 5
+ tmpdir.remove()
@mock.patch('deploy.environment.reboot_vm')
@@ -334,19 +492,29 @@ def test_reboot_nodes_VirtualEnvironment(mock_reboot_vm, tmpdir):
daisy_server, work_dir, storage_dir, scenario)
VirtualEnvironmentInst.reboot_nodes()
assert environment.reboot_vm.call_count == 5
+ tmpdir.remove()
+@pytest.mark.parametrize('isdir', [
+ (True),
+ (False)])
@mock.patch('deploy.environment.delete_virtual_network')
-def test_delete_networks_VirtualEnvironment(mock_delete_virtual_network, tmpdir):
+@mock.patch('deploy.environment.os.path.isdir')
+def test_delete_networks_VirtualEnvironment(mock_isdir, mock_delete_virtual_network, isdir, tmpdir):
work_dir = os.path.join(tmpdir.dirname, tmpdir.basename, work_dir_name)
storage_dir = os.path.join(tmpdir.dirname, tmpdir.basename, storage_dir_name)
daisy_server = copy.deepcopy(daisy_server_info)
daisy_server['image'] = os.path.join(storage_dir, daisy_server['image'])
+ mock_isdir.return_value = isdir
VirtualEnvironmentInst = VirtualEnvironment(
deploy_virtual_struct, net_struct, adapter_virtual, pxe_bridge_virtual,
daisy_server, work_dir, storage_dir, scenario)
VirtualEnvironmentInst.delete_networks()
- assert environment.delete_virtual_network.call_count == 3
+ if isdir is True:
+ assert mock_delete_virtual_network.call_count == 3
+ else:
+ mock_delete_virtual_network.assert_not_called()
+ tmpdir.remove()
@mock.patch.object(environment.DaisyEnvironmentBase, 'delete_daisy_server')
@@ -370,13 +538,72 @@ def test_delete_old_environment_VirtualEnvironment(mock_delete_daisy_server,
tmpdir.remove()
+@mock.patch.object(environment.DaisyServer, 'post_deploy')
+@mock.patch.object(environment.DaisyServer, 'check_openstack_installation')
+@mock.patch.object(environment.DaisyServer, 'check_os_installation')
+@mock.patch.object(environment.DaisyServer, 'install_virtual_nodes')
+@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.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_copy_new_deploy_config, mock_prepare_host_and_pxe,
+ mock_install_virtual_nodes, mock_check_os_installation,
+ mock_check_openstack_installation, mock_post_deploy,
+ tmpdir):
+ work_dir = os.path.join(tmpdir.dirname, tmpdir.basename, work_dir_name)
+ storage_dir = os.path.join(tmpdir.dirname, tmpdir.basename, storage_dir_name)
+ daisy_server = copy.deepcopy(daisy_server_info)
+ daisy_server['image'] = os.path.join(storage_dir, daisy_server['image'])
+ remote_dir = '/home/daisy'
+ bin_file = os.path.join(tmpdir.dirname, tmpdir.basename, 'opnfv.bin')
+ deploy_file_name = 'final_deploy.yml'
+ net_file_name = 'network_virtual1.yml'
+ deploy_file = os.path.join(get_conf_file_dir(), 'deploy_virtual1.yml')
+ net_file = os.path.join(get_conf_file_dir(), 'network_virtual1.yml')
+ VirtualEnvironmentInst = VirtualEnvironment(
+ deploy_virtual_struct, net_struct, adapter_virtual, pxe_bridge_virtual,
+ daisy_server, work_dir, storage_dir, scenario)
+ VirtualEnvironmentInst.server = DaisyServer(
+ daisy_server['name'],
+ daisy_server['address'],
+ daisy_server['password'],
+ remote_dir,
+ bin_file,
+ adapter,
+ scenario,
+ deploy_file_name,
+ net_file_name)
+ VirtualEnvironmentInst.deploy(deploy_file, net_file)
+ mock_create_nodes.assert_called_once()
+ assert mock_reboot_nodes.call_count == 2
+ mock__post_deploy.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()
+ mock_install_virtual_nodes.assert_called_once()
+ mock_check_os_installation.assert_called_once()
+ mock_check_openstack_installation.assert_called_once()
+ mock_post_deploy.assert_called_once()
+ tmpdir.remove()
+
+
+@pytest.mark.parametrize('status', [
+ (True),
+ (False)])
@mock.patch('deploy.environment.commands.getstatusoutput')
-def test_post_deploy_VirtualEnvironment(mock_getstatusoutput, tmpdir):
+@mock.patch('deploy.environment.LW')
+@mock.patch('deploy.environment.LI')
+def test__post_deploy_VirtualEnvironment(mock_LI, mock_LW,
+ mock_getstatusoutput, status, tmpdir):
work_dir = os.path.join(tmpdir.dirname, tmpdir.basename, work_dir_name)
storage_dir = os.path.join(tmpdir.dirname, tmpdir.basename, storage_dir_name)
daisy_server = copy.deepcopy(daisy_server_info)
daisy_server['image'] = os.path.join(storage_dir, daisy_server['image'])
- mock_getstatusoutput.return_value = (0, 'sucess')
+ mock_getstatusoutput.return_value = (status, 'success')
VirtualEnvironmentInst = VirtualEnvironment(
deploy_virtual_struct, net_struct, adapter_virtual, pxe_bridge_virtual,
daisy_server, work_dir, storage_dir, scenario)
@@ -384,3 +611,8 @@ def test_post_deploy_VirtualEnvironment(mock_getstatusoutput, tmpdir):
VirtualEnvironmentInst._daisy_server_net = 'daisy1'
VirtualEnvironmentInst._daisy_os_net = 'daisy2'
assert environment.commands.getstatusoutput.call_count == 4
+ if status:
+ mock_LW.assert_called()
+ else:
+ mock_LI.assert_called()
+ tmpdir.remove()
diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py
index 4cfe741d..e3b9dff7 100644
--- a/tests/unit/test_utils.py
+++ b/tests/unit/test_utils.py
@@ -9,73 +9,118 @@
import os
import pytest
import mock
+import shutil
from deploy import utils
from deploy.utils import (
+ get_logger,
+ save_log_to_file,
err_exit,
+ log_bar,
check_sudo_privilege,
check_file_exists,
make_file_executable,
confirm_dir_exists,
- check_scenario_valid
+ update_config,
+ ipmi_reboot_node,
+ run_shell,
+ check_scenario_valid,
+ LI
)
+@pytest.fixture(scope="module")
+def daisy_conf_file_dir(data_root):
+ return os.path.join(data_root, 'daisy_conf')
+
+
+@mock.patch.object(utils.logging.Logger, 'addHandler')
+def test_get_logger(mock_addHandler):
+ get_logger()
+ mock_addHandler.assert_called_once()
+
+
+@mock.patch.object(utils.logging.Logger, 'addHandler')
+def test_save_log_to_file(mock_addHandler, tmpdir):
+ log_file = os.path.join(tmpdir.dirname, tmpdir.basename, 'test_log.txt')
+ save_log_to_file(log_file)
+ mock_addHandler.assert_called_once()
+ tmpdir.remove()
+
+
def test_err_exit():
message = 'test error msg!'
with pytest.raises(SystemExit):
err_exit(message)
+def test_log_bar():
+ log_bar('test_messgae', log_func=LI)
+
+
@mock.patch('deploy.utils.err_exit')
@mock.patch('deploy.utils.os.getuid')
def test_check_sudo_privilege(mock_getuid, mock_err_exit):
mock_getuid.return_value = 1
check_sudo_privilege()
- utils.err_exit.assert_called_once_with('You need run this script with sudo privilege')
+ mock_err_exit.assert_called_once_with('You need run this script with sudo privilege')
-@pytest.mark.parametrize('test_file_name', [
- ('no_exist_file'),
- ('exist_file')])
-def test_check_file_exists(tmpdir, test_file_name):
- try:
+@pytest.mark.parametrize('test_file_name, include_dirname', [
+ ('no_exist_file', True),
+ ('exist_file', True),
+ ('no_exist_file', False),
+ ('exist_file', False)])
+@mock.patch('deploy.utils.err_exit')
+def test_check_file_exists(mock_err_exit, tmpdir, test_file_name, include_dirname):
+ if include_dirname:
file_path = os.path.join(tmpdir.dirname, tmpdir.basename, test_file_name)
if test_file_name == 'exist_file':
os.mknod(file_path)
- check_file_exists(file_path)
- except SystemExit:
- if test_file_name == 'exist_file':
- assert 0
else:
- if test_file_name == 'no_exist_file':
- assert 0
- finally:
- tmpdir.remove()
-
-
-@pytest.mark.parametrize('test_file_name', [
- ('no_exist_file'),
- ('no_exe_file'),
- ('exe_file')])
-def test_make_file_executable(tmpdir, test_file_name):
- try:
+ file_path = test_file_name
+ check_file_exists(file_path)
+ if include_dirname is True:
+ if test_file_name == 'exist_file':
+ mock_err_exit.assert_not_called()
+ else:
+ mock_err_exit.assert_called_once()
+ if include_dirname is False:
+ mock_err_exit.assert_called_once()
+ tmpdir.remove()
+
+
+@pytest.mark.parametrize('test_file_name, status, include_dir', [
+ ('no_exist_file', False, False),
+ ('no_exe_file', False, True),
+ ('no_exe_file', True, True),
+ ('exe_file', False, True)])
+@mock.patch('deploy.utils.commands.getstatusoutput')
+@mock.patch('deploy.utils.err_exit')
+def test_make_file_executable(mock_err_exit, mock_getstatusoutput,
+ tmpdir, test_file_name,
+ status, include_dir):
+ if include_dir:
file_path = os.path.join(tmpdir.dirname, tmpdir.basename, test_file_name)
- if test_file_name == 'no_exe_file':
- os.mknod(file_path)
- if test_file_name == 'exe_file':
- os.mknod(file_path, 0700)
- make_file_executable(file_path)
- except SystemExit:
- if test_file_name == 'no_exe_file' or test_file_name == 'exe_file':
- assert 0
else:
- if test_file_name == 'no_exist_file':
- assert 0
- finally:
- if test_file_name == 'no_exe_file' or test_file_name == 'exe_file':
- assert os.access(file_path, os.X_OK)
- tmpdir.remove()
+ file_path = test_file_name
+ if test_file_name == 'no_exe_file':
+ os.mknod(file_path)
+ if test_file_name == 'exe_file':
+ os.mknod(file_path, 0700)
+ output = 'test_out'
+ mock_getstatusoutput.return_value = (status, output)
+ make_file_executable(file_path)
+ if test_file_name == 'exe_file':
+ mock_err_exit.assert_not_called()
+ assert os.access(file_path, os.X_OK)
+ if test_file_name == 'no_exe_file' and status is False:
+ mock_err_exit.assert_not_called()
+ if test_file_name == 'no_exe_file' and status is True:
+ mock_err_exit.assert_called()
+ if test_file_name == 'no_exist_file':
+ mock_err_exit.assert_called()
+ tmpdir.remove()
@pytest.mark.parametrize('test_dir_name', [
@@ -92,6 +137,67 @@ def test_confirm_dir_exists(tmpdir, test_dir_name):
tmpdir.remove()
+def test_update_config(daisy_conf_file_dir, tmpdir):
+ src_daisy_conf_file = os.path.join(daisy_conf_file_dir, 'daisy.conf')
+ dst_daisy_conf_file = os.path.join(tmpdir.dirname, tmpdir.basename, 'daisy.conf')
+ shutil.copyfile(src_daisy_conf_file, dst_daisy_conf_file)
+ key = 'daisy_management_ip'
+ value = '10.20.11.2'
+ update_line = 'daisy_management_ip = 10.20.11.2'
+ is_match = False
+ update_config(dst_daisy_conf_file, key, value, section='DEFAULT')
+ with open(dst_daisy_conf_file) as f:
+ lines = f.readlines()
+ for line in lines:
+ line_content = line.strip()
+ if update_line in line_content:
+ is_match = True
+ break
+ assert is_match
+ tmpdir.remove()
+
+
+@pytest.mark.parametrize('boot_source, status', [
+ (None, 0),
+ (None, 1),
+ ('test_source', 0),
+ ('test_source', 1)])
+@mock.patch('deploy.utils.err_exit')
+@mock.patch.object(utils.commands, 'getstatusoutput')
+def test_ipmi_reboot_node(mock_getstatusoutput, mock_err_exit,
+ boot_source, status):
+ host = '192.168.1.11'
+ user = 'testuser'
+ passwd = 'testpass'
+ output = 'test_out'
+ mock_getstatusoutput.return_value = (status, output)
+ ipmi_reboot_node(host, user, passwd, boot_source=boot_source)
+ if boot_source:
+ assert mock_getstatusoutput.call_count == 2
+ if status:
+ assert mock_err_exit.call_count == 2
+ else:
+ mock_getstatusoutput.called_once()
+ if status:
+ mock_err_exit.called_once()
+
+
+@pytest.mark.parametrize('cmd, check, expect', [
+ ('cd /home', False, 0),
+ ('cd /home', True, 0),
+ ('test_command', False, 127),
+ ('test_command', True, 127)])
+@mock.patch('deploy.utils.err_exit')
+def test_run_shell(mock_err_exit, cmd, check, expect):
+ ret = run_shell(cmd, check=check)
+ if check:
+ if cmd == 'cd /home':
+ mock_err_exit.assert_not_called()
+ elif cmd == 'test_command':
+ mock_err_exit.assert_called_once()
+ assert ret == expect
+
+
@pytest.mark.parametrize('scenario', [
('os-nosdn-nofeature-ha')])
@mock.patch("deploy.utils.err_exit")