Enables containerized overcloud deployments
[apex.git] / apex / tests / test_apex_undercloud.py
1 ##############################################################################
2 # Copyright (c) 2016 Dan Radez (dradez@redhat.com) (Red Hat)
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10 import ipaddress
11 import libvirt
12 import os
13 import subprocess
14 import unittest
15
16 from mock import patch
17 from mock import MagicMock
18
19 from apex.common import constants
20 from apex.undercloud.undercloud import Undercloud
21 from apex.undercloud.undercloud import ApexUndercloudException
22
23 from nose.tools import (
24     assert_regexp_matches,
25     assert_raises,
26     assert_true,
27     assert_equal)
28
29
30 class TestUndercloud(unittest.TestCase):
31     @classmethod
32     def setup_class(cls):
33         """This method is run once for each class before any tests are run"""
34
35     @classmethod
36     def teardown_class(cls):
37         """This method is run once for each class _after_ all tests are run"""
38
39     def setup(self):
40         """This method is run once before _each_ test method is executed"""
41
42     def teardown(self):
43         """This method is run once after _each_ test method is executed"""
44
45     @patch.object(Undercloud, '_get_vm', return_value=None)
46     @patch.object(Undercloud, 'create')
47     def test_init(self, mock_get_vm, mock_create):
48         Undercloud('img_path', 'tplt_path')
49         mock_create.assert_called()
50
51     @patch.object(Undercloud, '_get_vm', return_value=object())
52     @patch.object(Undercloud, 'create')
53     def test_init_uc_exists(self, mock_get_vm, mock_create):
54         assert_raises(ApexUndercloudException,
55                       Undercloud, 'img_path', 'tplt_path')
56
57     @patch('apex.undercloud.undercloud.libvirt.open')
58     @patch.object(Undercloud, 'create')
59     def test_get_vm_exists(self, mock_create, mock_libvirt):
60         assert_raises(ApexUndercloudException,
61                       Undercloud, 'img_path', 'tplt_path')
62
63     @patch('apex.undercloud.undercloud.libvirt.open')
64     @patch.object(Undercloud, 'create')
65     def test_get_vm_not_exists(self, mock_create, mock_libvirt):
66         conn = mock_libvirt.return_value
67         conn.lookupByName.side_effect = libvirt.libvirtError('defmsg')
68         Undercloud('img_path', 'tplt_path')
69
70     @patch('apex.undercloud.undercloud.vm_lib')
71     @patch.object(Undercloud, 'inject_auth', return_value=None)
72     @patch.object(Undercloud, 'setup_volumes', return_value=None)
73     @patch.object(Undercloud, '_get_vm', return_value=None)
74     def test_create(self, mock_get_vm, mock_setup_vols,
75                     mock_inject_auth, mock_vm_lib):
76         Undercloud('img_path', 'tplt_path', external_network=True)
77         mock_inject_auth.assert_called()
78         mock_setup_vols.assert_called()
79         mock_inject_auth.assert_called()
80
81     @patch.object(Undercloud, '_get_vm', return_value=None)
82     @patch.object(Undercloud, 'create')
83     def test_set_ip(self, mock_get_vm, mock_create):
84         uc = Undercloud('img_path', 'tplt_path', external_network=True)
85         uc.vm = MagicMock()
86         if_addrs = {'item1': {'addrs': [{'type': libvirt.VIR_IP_ADDR_TYPE_IPV4,
87                                          'addr': 'ipaddress'}]},
88                     'item2': {'addrs': [{'type': libvirt.VIR_IP_ADDR_TYPE_IPV4,
89                                          'addr': 'ipaddress'}]}}
90         uc.vm.interfaceAddresses.return_value = if_addrs
91         assert_true(uc._set_ip())
92
93     @patch('apex.undercloud.undercloud.time.sleep')
94     @patch.object(Undercloud, '_set_ip', return_value=False)
95     @patch.object(Undercloud, '_get_vm', return_value=None)
96     @patch.object(Undercloud, 'create')
97     def test_start(self, mock_create, mock_get_vm,
98                    mock_set_ip, mock_time):
99         uc = Undercloud('img_path', 'tplt_path', external_network=True)
100         uc.vm = MagicMock()
101         uc.vm.isActive.return_value = False
102         mock_set_ip.return_value = True
103         uc.start()
104
105     @patch('apex.undercloud.undercloud.time.sleep')
106     @patch.object(Undercloud, '_set_ip', return_value=False)
107     @patch.object(Undercloud, '_get_vm', return_value=None)
108     @patch.object(Undercloud, 'create')
109     def test_start_no_ip(self, mock_create, mock_get_vm,
110                          mock_set_ip, mock_time):
111         uc = Undercloud('img_path', 'tplt_path', external_network=True)
112         uc.vm = MagicMock()
113         uc.vm.isActive.return_value = True
114         mock_set_ip.return_value = False
115         assert_raises(ApexUndercloudException, uc.start)
116
117     @patch('apex.undercloud.undercloud.utils')
118     @patch.object(Undercloud, 'generate_config', return_value={})
119     @patch.object(Undercloud, '_get_vm', return_value=None)
120     @patch.object(Undercloud, 'create')
121     def test_configure(self, mock_create, mock_get_vm,
122                        mock_generate_config, mock_utils):
123         uc = Undercloud('img_path', 'tplt_path', external_network=True)
124         ns = MagicMock()
125         ds = MagicMock()
126         uc.configure(ns, ds, 'playbook', '/tmp/dir')
127
128     @patch('apex.undercloud.undercloud.utils')
129     @patch.object(Undercloud, 'generate_config', return_value={})
130     @patch.object(Undercloud, '_get_vm', return_value=None)
131     @patch.object(Undercloud, 'create')
132     def test_configure_raises(self, mock_create, mock_get_vm,
133                               mock_generate_config, mock_utils):
134         uc = Undercloud('img_path', 'tplt_path', external_network=True)
135         ns = MagicMock()
136         ds = MagicMock()
137         subps_err = subprocess.CalledProcessError(1, 'cmd')
138         mock_utils.run_ansible.side_effect = subps_err
139         assert_raises(ApexUndercloudException,
140                       uc.configure, ns, ds, 'playbook', '/tmp/dir')
141
142     @patch('apex.undercloud.undercloud.os.remove')
143     @patch('apex.undercloud.undercloud.os.path')
144     @patch('apex.undercloud.undercloud.shutil')
145     @patch.object(Undercloud, '_get_vm', return_value=None)
146     @patch.object(Undercloud, 'create')
147     def test_setup_vols(self, mock_get_vm, mock_create,
148                         mock_shutil, mock_os_path, mock_os_remove):
149         uc = Undercloud('img_path', 'tplt_path', external_network=True)
150         mock_os_path.isfile.return_value = True
151         mock_os_path.exists.return_value = True
152         uc.setup_volumes()
153         for img_file in ('overcloud-full.vmlinuz', 'overcloud-full.initrd',
154                          'undercloud.qcow2'):
155             src_img = os.path.join(uc.image_path, img_file)
156             dest_img = os.path.join(constants.LIBVIRT_VOLUME_PATH, img_file)
157             mock_shutil.copyfile.assert_called_with(src_img, dest_img)
158
159     @patch('apex.undercloud.undercloud.os.path')
160     @patch.object(Undercloud, '_get_vm', return_value=None)
161     @patch.object(Undercloud, 'create')
162     def test_setup_vols_raises(self, mock_get_vm, mock_create, mock_os_path):
163         uc = Undercloud('img_path', 'tplt_path', external_network=True)
164         mock_os_path.isfile.return_value = False
165         assert_raises(ApexUndercloudException, uc.setup_volumes)
166
167     @patch('apex.undercloud.undercloud.virt_utils')
168     @patch.object(Undercloud, '_get_vm', return_value=None)
169     @patch.object(Undercloud, 'create')
170     def test_inject_auth(self, mock_get_vm, mock_create, mock_vutils):
171         uc = Undercloud('img_path', 'tplt_path', external_network=True)
172         uc.root_pw = 'test'
173         uc.inject_auth()
174         test_ops = [{'--root-password': 'password:test'},
175                     {'--run-command': 'mkdir -p /root/.ssh'},
176                     {'--upload':
177                      '/root/.ssh/id_rsa.pub:/root/.ssh/authorized_keys'},
178                     {'--run-command': 'chmod 600 /root/.ssh/authorized_keys'},
179                     {'--run-command': 'restorecon /root/.ssh/authorized_keys'},
180                     {'--run-command':
181                      'cp /root/.ssh/authorized_keys /home/stack/.ssh/'},
182                     {'--run-command':
183                      'chown stack:stack /home/stack/.ssh/authorized_keys'},
184                     {'--run-command':
185                      'chmod 600 /home/stack/.ssh/authorized_keys'}]
186         mock_vutils.virt_customize.assert_called_with(test_ops, uc.volume)
187
188     @patch.object(Undercloud, '_get_vm', return_value=None)
189     @patch.object(Undercloud, 'create')
190     def test_generate_config(self, mock_get_vm, mock_create):
191         ns = MagicMock()
192         ns.enabled_network_list = ['admin', 'external']
193         ns_dict = {
194             'apex': MagicMock(),
195             'dns-domain': 'dns',
196             'networks': {'admin':
197                          {'cidr': ipaddress.ip_network('192.0.2.0/24'),
198                           'installer_vm': {'ip': '192.0.2.1',
199                                            'vlan': 'native'},
200                           'dhcp_range': ['192.0.2.15', '192.0.2.30']
201                           },
202                          'external':
203                          [{'enabled': True,
204                            'cidr': ipaddress.ip_network('192.168.0.0/24'),
205                           'installer_vm': {'ip': '192.168.0.1',
206                                            'vlan': 'native'}
207                            }]
208                          }
209         }
210         ns.__getitem__.side_effect = ns_dict.__getitem__
211         ns.__contains__.side_effect = ns_dict.__contains__
212         ds = {'global_params': {}}
213
214         Undercloud('img_path', 'tplt_path').generate_config(ns, ds)
215
216     @patch.object(Undercloud, '_get_vm', return_value=None)
217     @patch.object(Undercloud, 'create')
218     @patch('apex.undercloud.undercloud.virt_utils')
219     def test_update_delorean(self, mock_vutils, mock_uc_create, mock_get_vm):
220         uc = Undercloud('img_path', 'tmplt_path', external_network=True)
221         uc._update_delorean_repo()
222         download_cmd = (
223             "curl -L -f -o "
224             "/etc/yum.repos.d/deloran.repo "
225             "https://trunk.rdoproject.org/centos7-{}"
226             "/current-tripleo/delorean.repo".format(
227                 constants.DEFAULT_OS_VERSION))
228         test_ops = {'--run-command': download_cmd}
229         mock_vutils.virt_customize.assert_called_with(test_ops, uc.volume)