Remove downloading undercloud.qcow2
[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 platform
14 import subprocess
15 import unittest
16
17 from mock import patch
18 from mock import MagicMock
19
20 from apex.common import constants
21 from apex.undercloud.undercloud import Undercloud
22 from apex.undercloud.undercloud import ApexUndercloudException
23
24 from nose.tools import (
25     assert_regexp_matches,
26     assert_raises,
27     assert_true,
28     assert_false,
29     assert_equal)
30
31
32 class TestUndercloud(unittest.TestCase):
33     @classmethod
34     def setup_class(cls):
35         """This method is run once for each class before any tests are run"""
36
37     @classmethod
38     def teardown_class(cls):
39         """This method is run once for each class _after_ all tests are run"""
40
41     def setup(self):
42         """This method is run once before _each_ test method is executed"""
43
44     def teardown(self):
45         """This method is run once after _each_ test method is executed"""
46
47     @patch.object(Undercloud, '_get_vm', return_value=None)
48     @patch.object(Undercloud, 'create')
49     def test_init(self, mock_get_vm, mock_create):
50         Undercloud('img_path', 'tplt_path')
51         mock_create.assert_called()
52
53     @patch.object(Undercloud, '_get_vm', return_value=object())
54     @patch.object(Undercloud, 'create')
55     def test_init_uc_exists(self, mock_get_vm, mock_create):
56         assert_raises(ApexUndercloudException,
57                       Undercloud, 'img_path', 'tplt_path')
58
59     @patch('apex.undercloud.undercloud.libvirt.open')
60     @patch.object(Undercloud, 'create')
61     def test_get_vm_exists(self, mock_create, mock_libvirt):
62         assert_raises(ApexUndercloudException,
63                       Undercloud, 'img_path', 'tplt_path')
64
65     @patch('apex.undercloud.undercloud.libvirt.open')
66     @patch.object(Undercloud, 'create')
67     def test_get_vm_not_exists(self, mock_create, mock_libvirt):
68         conn = mock_libvirt.return_value
69         conn.lookupByName.side_effect = libvirt.libvirtError('defmsg')
70         Undercloud('img_path', 'tplt_path')
71
72     @patch('apex.undercloud.undercloud.vm_lib')
73     @patch.object(Undercloud, 'inject_auth', return_value=None)
74     @patch.object(Undercloud, 'setup_volumes', return_value=None)
75     @patch.object(Undercloud, '_get_vm', return_value=None)
76     def test_create(self, mock_get_vm, mock_setup_vols,
77                     mock_inject_auth, mock_vm_lib):
78         Undercloud('img_path', 'tplt_path', external_network=True)
79         mock_inject_auth.assert_called()
80         mock_setup_vols.assert_called()
81         mock_inject_auth.assert_called()
82
83     @patch.object(Undercloud, '_get_vm', return_value=None)
84     @patch.object(Undercloud, 'create')
85     def test_set_ip(self, mock_get_vm, mock_create):
86         uc = Undercloud('img_path', 'tplt_path', external_network=True)
87         uc.vm = MagicMock()
88         if_addrs = {'item1': {'addrs': [{'type': libvirt.VIR_IP_ADDR_TYPE_IPV4,
89                                          'addr': 'ipaddress'}]},
90                     'item2': {'addrs': [{'type': libvirt.VIR_IP_ADDR_TYPE_IPV4,
91                                          'addr': 'ipaddress'}]}}
92         uc.vm.interfaceAddresses.return_value = if_addrs
93         assert_true(uc._set_ip())
94
95     @patch('apex.undercloud.undercloud.time.sleep')
96     @patch.object(Undercloud, '_set_ip', return_value=False)
97     @patch.object(Undercloud, '_get_vm', return_value=None)
98     @patch.object(Undercloud, 'create')
99     def test_start(self, mock_create, mock_get_vm,
100                    mock_set_ip, mock_time):
101         uc = Undercloud('img_path', 'tplt_path', external_network=True)
102         uc.vm = MagicMock()
103         uc.vm.isActive.return_value = False
104         mock_set_ip.return_value = True
105         uc.start()
106
107     @patch('apex.undercloud.undercloud.time.sleep')
108     @patch.object(Undercloud, '_set_ip', return_value=False)
109     @patch.object(Undercloud, '_get_vm', return_value=None)
110     @patch.object(Undercloud, 'create')
111     def test_start_no_ip(self, mock_create, mock_get_vm,
112                          mock_set_ip, mock_time):
113         uc = Undercloud('img_path', 'tplt_path', external_network=True)
114         uc.vm = MagicMock()
115         uc.vm.isActive.return_value = True
116         mock_set_ip.return_value = False
117         assert_raises(ApexUndercloudException, uc.start)
118
119     @patch('apex.undercloud.undercloud.utils')
120     @patch.object(Undercloud, 'generate_config', return_value={})
121     @patch.object(Undercloud, '_get_vm', return_value=None)
122     @patch.object(Undercloud, 'create')
123     def test_detect_nat_with_external(self, mock_create, mock_get_vm,
124                                       mock_generate_config, mock_utils):
125         ns = MagicMock()
126         ns.enabled_network_list = ['admin', 'external']
127         ns_dict = {
128             'apex': MagicMock(),
129             'dns-domain': 'dns',
130             'networks': {'admin':
131                          {'cidr': ipaddress.ip_network('192.0.2.0/24'),
132                           'installer_vm': {'ip': '192.0.2.1',
133                                            'vlan': 'native'},
134                           'dhcp_range': ['192.0.2.15', '192.0.2.30'],
135                           'gateway': '192.1.1.1',
136                           },
137                          'external':
138                          [{'enabled': True,
139                            'cidr': ipaddress.ip_network('192.168.0.0/24'),
140                           'installer_vm': {'ip': '192.168.0.1',
141                                            'vlan': 'native'},
142                            'gateway': '192.168.0.1'
143                            }]
144                          }
145         }
146         ns.__getitem__.side_effect = ns_dict.__getitem__
147         ns.__contains__.side_effect = ns_dict.__contains__
148
149         uc = Undercloud('img_path', 'tplt_path', external_network=True)
150         assert_true(uc.detect_nat(ns))
151
152     @patch('apex.undercloud.undercloud.utils')
153     @patch.object(Undercloud, 'generate_config', return_value={})
154     @patch.object(Undercloud, '_get_vm', return_value=None)
155     @patch.object(Undercloud, 'create')
156     def test_detect_nat_no_external(self, mock_create, mock_get_vm,
157                                     mock_generate_config, mock_utils):
158         ns = MagicMock()
159         ns.enabled_network_list = ['admin', 'external']
160         ns_dict = {
161             'apex': MagicMock(),
162             'dns-domain': 'dns',
163             'networks': {'admin':
164                          {'cidr': ipaddress.ip_network('192.0.2.0/24'),
165                           'installer_vm': {'ip': '192.0.2.1',
166                                            'vlan': 'native'},
167                           'dhcp_range': ['192.0.2.15', '192.0.2.30'],
168                           'gateway': '192.0.2.1',
169                           },
170                          'external':
171                          [{'enabled': False,
172                            'cidr': ipaddress.ip_network('192.168.0.0/24'),
173                           'installer_vm': {'ip': '192.168.0.1',
174                                            'vlan': 'native'},
175                            'gateway': '192.168.1.1'
176                            }]
177                          }
178         }
179         ns.__getitem__.side_effect = ns_dict.__getitem__
180         ns.__contains__.side_effect = ns_dict.__contains__
181
182         uc = Undercloud('img_path', 'tplt_path', external_network=False)
183         assert_true(uc.detect_nat(ns))
184
185     @patch('apex.undercloud.undercloud.utils')
186     @patch.object(Undercloud, 'generate_config', return_value={})
187     @patch.object(Undercloud, '_get_vm', return_value=None)
188     @patch.object(Undercloud, 'create')
189     def test_detect_no_nat_no_external(self, mock_create, mock_get_vm,
190                                        mock_generate_config, mock_utils):
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                           'gateway': '192.0.2.3',
202                           },
203                          'external':
204                          [{'enabled': False,
205                            'cidr': ipaddress.ip_network('192.168.0.0/24'),
206                           'installer_vm': {'ip': '192.168.0.1',
207                                            'vlan': 'native'},
208                            'gateway': '192.168.1.1'
209                            }]
210                          }
211         }
212         ns.__getitem__.side_effect = ns_dict.__getitem__
213         ns.__contains__.side_effect = ns_dict.__contains__
214
215         uc = Undercloud('img_path', 'tplt_path', external_network=False)
216         assert_false(uc.detect_nat(ns))
217
218     @patch('apex.undercloud.undercloud.utils')
219     @patch.object(Undercloud, 'generate_config', return_value={})
220     @patch.object(Undercloud, '_get_vm', return_value=None)
221     @patch.object(Undercloud, 'create')
222     def test_configure(self, mock_create, mock_get_vm,
223                        mock_generate_config, mock_utils):
224         uc = Undercloud('img_path', 'tplt_path', external_network=True)
225         ns = MagicMock()
226         ds = MagicMock()
227         uc.configure(ns, ds, 'playbook', '/tmp/dir')
228
229     @patch('apex.undercloud.undercloud.utils')
230     @patch.object(Undercloud, 'generate_config', return_value={})
231     @patch.object(Undercloud, '_get_vm', return_value=None)
232     @patch.object(Undercloud, 'create')
233     def test_configure_raises(self, mock_create, mock_get_vm,
234                               mock_generate_config, mock_utils):
235         uc = Undercloud('img_path', 'tplt_path', external_network=True)
236         ns = MagicMock()
237         ds = MagicMock()
238         subps_err = subprocess.CalledProcessError(1, 'cmd')
239         mock_utils.run_ansible.side_effect = subps_err
240         assert_raises(ApexUndercloudException,
241                       uc.configure, ns, ds, 'playbook', '/tmp/dir')
242
243     @patch('apex.undercloud.undercloud.virt_utils')
244     @patch('apex.undercloud.undercloud.uc_builder')
245     @patch('apex.undercloud.undercloud.os.remove')
246     @patch('apex.undercloud.undercloud.os.path')
247     @patch('apex.undercloud.undercloud.shutil')
248     @patch.object(Undercloud, '_get_vm', return_value=None)
249     @patch.object(Undercloud, 'create')
250     def test_setup_vols(self, mock_get_vm, mock_create,
251                         mock_shutil, mock_os_path, mock_os_remove,
252                         mock_uc_builder, mock_virt_utils):
253         uc = Undercloud('img_path', 'tplt_path', external_network=True)
254         mock_os_path.isfile.return_value = True
255         mock_os_path.exists.return_value = True
256         uc.setup_volumes()
257         for img_file in ('overcloud-full.vmlinuz', 'overcloud-full.initrd',
258                          'undercloud.qcow2'):
259             src_img = os.path.join(uc.image_path, img_file)
260             dest_img = os.path.join(constants.LIBVIRT_VOLUME_PATH, img_file)
261             mock_shutil.copyfile.assert_called_with(src_img, dest_img)
262         if platform.machine() != 'aarch64':
263             mock_uc_builder.expand_disk.assert_called()
264             mock_virt_utils.virt_customize.assert_called()
265
266     @patch('apex.undercloud.undercloud.os.path')
267     @patch.object(Undercloud, '_get_vm', return_value=None)
268     @patch.object(Undercloud, 'create')
269     def test_setup_vols_raises(self, mock_get_vm, mock_create, mock_os_path):
270         uc = Undercloud('img_path', 'tplt_path', external_network=True)
271         mock_os_path.isfile.return_value = False
272         assert_raises(ApexUndercloudException, uc.setup_volumes)
273
274     @patch('apex.undercloud.undercloud.virt_utils')
275     @patch.object(Undercloud, '_get_vm', return_value=None)
276     @patch.object(Undercloud, 'create')
277     def test_inject_auth(self, mock_get_vm, mock_create, mock_vutils):
278         uc = Undercloud('img_path', 'tplt_path', external_network=True)
279         uc.root_pw = 'test'
280         uc.inject_auth()
281         test_ops = [{'--root-password': 'password:test'},
282                     {'--run-command': 'mkdir -p /root/.ssh'},
283                     {'--upload':
284                      '/root/.ssh/id_rsa.pub:/root/.ssh/authorized_keys'},
285                     {'--run-command': 'chmod 600 /root/.ssh/authorized_keys'},
286                     {'--run-command': 'restorecon '
287                                       '-R -v /root/.ssh'},
288                     {'--run-command': 'id -u stack || useradd -m stack'},
289                     {'--run-command': 'mkdir -p /home/stack/.ssh'},
290                     {'--run-command': 'chown stack:stack /home/stack/.ssh'},
291                     {'--run-command':
292                      'cp /root/.ssh/authorized_keys /home/stack/.ssh/'},
293                     {'--run-command':
294                      'chown stack:stack /home/stack/.ssh/authorized_keys'},
295                     {'--run-command':
296                      'chmod 600 /home/stack/.ssh/authorized_keys'},
297                     {'--run-command':
298                      'echo "stack       ALL = (ALL) NOPASSWD: ALL" >> '
299                      '/etc/sudoers'},
300                     {'--run-command': 'touch /etc/cloud/cloud-init.disabled'}]
301         mock_vutils.virt_customize.assert_called_with(test_ops, uc.volume)
302
303     @patch.object(Undercloud, '_get_vm', return_value=None)
304     @patch.object(Undercloud, 'create')
305     def test_generate_config(self, mock_get_vm, mock_create):
306         ns = MagicMock()
307         ns.enabled_network_list = ['admin', 'external']
308         ns_dict = {
309             'apex': MagicMock(),
310             'dns-domain': 'dns',
311             'ntp': 'pool.ntp.org',
312             'networks': {'admin':
313                          {'cidr': ipaddress.ip_network('192.0.2.0/24'),
314                           'installer_vm': {'ip': '192.0.2.1',
315                                            'vlan': 'native'},
316                           'dhcp_range': ['192.0.2.15', '192.0.2.30']
317                           },
318                          'external':
319                          [{'enabled': True,
320                            'cidr': ipaddress.ip_network('192.168.0.0/24'),
321                           'installer_vm': {'ip': '192.168.0.1',
322                                            'vlan': 'native'}
323                            }]
324                          }
325         }
326         ns.__getitem__.side_effect = ns_dict.__getitem__
327         ns.__contains__.side_effect = ns_dict.__contains__
328         ds = {'global_params': {},
329               'deploy_options': {}}
330
331         Undercloud('img_path', 'tplt_path').generate_config(ns, ds)
332
333     @patch.object(Undercloud, '_get_vm', return_value=None)
334     @patch.object(Undercloud, 'create')
335     @patch('apex.undercloud.undercloud.virt_utils')
336     def test_update_delorean(self, mock_vutils, mock_uc_create, mock_get_vm):
337         uc = Undercloud('img_path', 'tmplt_path', external_network=True)
338         uc._update_delorean_repo()
339         download_cmd = (
340             "curl -L -f -o "
341             "/etc/yum.repos.d/deloran.repo "
342             "https://trunk.rdoproject.org/centos7-{}"
343             "/current-tripleo/delorean.repo".format(
344                 constants.DEFAULT_OS_VERSION))
345         test_ops = [{'--run-command': download_cmd}]
346         mock_vutils.virt_customize.assert_called_with(test_ops, uc.volume)