Improved creator/state machine classes class hierarchy.
[snaps.git] / snaps / openstack / utils / tests / nova_utils_tests.py
1 # Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
2 #                    and others.  All rights reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 import logging
16 import uuid
17
18 import os
19 import time
20
21 from snaps import file_utils
22 from snaps.openstack import create_instance
23 from snaps.openstack.create_flavor import FlavorSettings, OpenStackFlavor
24 from snaps.openstack.create_image import OpenStackImage
25 from snaps.openstack.create_instance import VmInstanceSettings
26 from snaps.openstack.create_network import OpenStackNetwork, PortSettings
27 from snaps.openstack.tests import openstack_tests
28 from snaps.openstack.tests.os_source_file_test import OSComponentTestCase
29 from snaps.openstack.utils import nova_utils, neutron_utils, glance_utils
30
31 __author__ = 'spisarski'
32
33 logger = logging.getLogger('nova_utils_tests')
34
35
36 class NovaSmokeTests(OSComponentTestCase):
37     """
38     Tests to ensure that the nova client can communicate with the cloud
39     """
40
41     def test_nova_connect_success(self):
42         """
43         Tests to ensure that the proper credentials can connect.
44         """
45         nova = nova_utils.nova_client(self.os_creds)
46
47         # This should not throw an exception
48         nova.flavors.list()
49
50     def test_nova_connect_fail(self):
51         """
52         Tests to ensure that the improper credentials cannot connect.
53         """
54         from snaps.openstack.os_credentials import OSCreds
55
56         nova = nova_utils.nova_client(
57             OSCreds(username='user', password='pass',
58                     auth_url=self.os_creds.auth_url,
59                     project_name=self.os_creds.project_name,
60                     proxy_settings=self.os_creds.proxy_settings))
61
62         # This should throw an exception
63         with self.assertRaises(Exception):
64             nova.flavors.list()
65
66
67 class NovaUtilsKeypairTests(OSComponentTestCase):
68     """
69     Test basic nova keypair functionality
70     """
71
72     def setUp(self):
73         """
74         Instantiates the CreateImage object that is responsible for downloading
75         and creating an OS image file within OpenStack
76         """
77         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
78         self.priv_key_file_path = 'tmp/' + guid
79         self.pub_key_file_path = self.priv_key_file_path + '.pub'
80
81         self.nova = nova_utils.nova_client(self.os_creds)
82         self.keys = nova_utils.create_keys()
83         self.public_key = nova_utils.public_key_openssh(self.keys)
84         self.keypair_name = guid
85         self.keypair = None
86
87     def tearDown(self):
88         """
89         Cleans the image and downloaded image file
90         """
91         if self.keypair:
92             try:
93                 nova_utils.delete_keypair(self.nova, self.keypair)
94             except:
95                 pass
96
97         try:
98             os.chmod(self.priv_key_file_path, 0o777)
99             os.remove(self.priv_key_file_path)
100         except:
101             pass
102
103         try:
104             os.chmod(self.pub_key_file_path, 0o777)
105             os.remove(self.pub_key_file_path)
106         except:
107             pass
108
109     def test_create_keypair(self):
110         """
111         Tests the creation of an OpenStack keypair that does not exist.
112         """
113         self.keypair = nova_utils.upload_keypair(self.nova, self.keypair_name,
114                                                  self.public_key)
115         result = nova_utils.keypair_exists(self.nova, self.keypair)
116         self.assertEqual(self.keypair, result)
117         keypair = nova_utils.get_keypair_by_name(self.nova, self.keypair_name)
118         self.assertEqual(self.keypair, keypair)
119
120     def test_create_delete_keypair(self):
121         """
122         Tests the creation of an OpenStack keypair that does not exist.
123         """
124         self.keypair = nova_utils.upload_keypair(self.nova, self.keypair_name,
125                                                  self.public_key)
126         result = nova_utils.keypair_exists(self.nova, self.keypair)
127         self.assertEqual(self.keypair, result)
128         nova_utils.delete_keypair(self.nova, self.keypair)
129         result2 = nova_utils.keypair_exists(self.nova, self.keypair)
130         self.assertIsNone(result2)
131
132     def test_create_key_from_file(self):
133         """
134         Tests that the generated RSA keys are properly saved to files
135         :return:
136         """
137         file_utils.save_keys_to_files(self.keys, self.pub_key_file_path,
138                                       self.priv_key_file_path)
139         self.keypair = nova_utils.upload_keypair_file(self.nova,
140                                                       self.keypair_name,
141                                                       self.pub_key_file_path)
142         pub_key_file = open(os.path.expanduser(self.pub_key_file_path))
143         pub_key = pub_key_file.read()
144         pub_key_file.close()
145         self.assertEqual(self.keypair.public_key, pub_key)
146
147
148 class NovaUtilsFlavorTests(OSComponentTestCase):
149     """
150     Test basic nova flavor functionality
151     """
152
153     def setUp(self):
154         """
155         Instantiates the CreateImage object that is responsible for downloading
156         and creating an OS image file within OpenStack
157         """
158         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
159         self.flavor_settings = FlavorSettings(name=guid + '-name',
160                                               flavor_id=guid + '-id', ram=1,
161                                               disk=1, vcpus=1,
162                                               ephemeral=1, swap=2,
163                                               rxtx_factor=3.0, is_public=False)
164         self.nova = nova_utils.nova_client(self.os_creds)
165         self.flavor = None
166
167     def tearDown(self):
168         """
169         Cleans the image and downloaded image file
170         """
171         if self.flavor:
172             try:
173                 nova_utils.delete_flavor(self.nova, self.flavor)
174             except:
175                 pass
176
177     def test_create_flavor(self):
178         """
179         Tests the creation of an OpenStack keypair that does not exist.
180         """
181         self.flavor = nova_utils.create_flavor(self.nova, self.flavor_settings)
182         self.validate_flavor()
183
184     def test_create_delete_flavor(self):
185         """
186         Tests the creation of an OpenStack keypair that does not exist.
187         """
188         self.flavor = nova_utils.create_flavor(self.nova, self.flavor_settings)
189         self.validate_flavor()
190         nova_utils.delete_flavor(self.nova, self.flavor)
191         flavor = nova_utils.get_flavor_by_name(self.nova,
192                                                self.flavor_settings.name)
193         self.assertIsNone(flavor)
194
195     def validate_flavor(self):
196         """
197         Validates the flavor_settings against the OpenStack flavor object
198         """
199         self.assertIsNotNone(self.flavor)
200         self.assertEqual(self.flavor_settings.name, self.flavor.name)
201         self.assertEqual(self.flavor_settings.flavor_id, self.flavor.id)
202         self.assertEqual(self.flavor_settings.ram, self.flavor.ram)
203         self.assertEqual(self.flavor_settings.disk, self.flavor.disk)
204         self.assertEqual(self.flavor_settings.vcpus, self.flavor.vcpus)
205         self.assertEqual(self.flavor_settings.ephemeral, self.flavor.ephemeral)
206
207         if self.flavor_settings.swap == 0:
208             self.assertEqual('', self.flavor.swap)
209         else:
210             self.assertEqual(self.flavor_settings.swap, self.flavor.swap)
211
212         self.assertEqual(self.flavor_settings.rxtx_factor,
213                          self.flavor.rxtx_factor)
214         self.assertEqual(self.flavor_settings.is_public, self.flavor.is_public)
215
216
217 class NovaUtilsInstanceTests(OSComponentTestCase):
218     """
219     Tests the creation of VM instances via nova_utils.py
220     """
221
222     def setUp(self):
223         """
224         Setup objects required by VM instances
225         :return:
226         """
227
228         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
229
230         self.nova = nova_utils.nova_client(self.os_creds)
231         self.neutron = neutron_utils.neutron_client(self.os_creds)
232         self.glance = glance_utils.glance_client(self.os_creds)
233
234         self.image_creator = None
235         self.network_creator = None
236         self.flavor_creator = None
237         self.port = None
238         self.vm_inst = None
239
240         try:
241             image_settings = openstack_tests.cirros_image_settings(
242                 name=guid + '-image', image_metadata=self.image_metadata)
243             self.image_creator = OpenStackImage(
244                 self.os_creds, image_settings=image_settings)
245             self.image_creator.create()
246
247             network_settings = openstack_tests.get_priv_net_config(
248                 guid + '-net', guid + '-subnet').network_settings
249             self.network_creator = OpenStackNetwork(
250                 self.os_creds, network_settings)
251             self.network_creator.create()
252
253             self.flavor_creator = OpenStackFlavor(
254                 self.os_creds,
255                 FlavorSettings(
256                     name=guid + '-flavor-name', ram=256, disk=10, vcpus=1))
257             self.flavor_creator.create()
258
259             port_settings = PortSettings(name=guid + '-port',
260                                          network_name=network_settings.name)
261             self.port = neutron_utils.create_port(
262                 self.neutron, self.os_creds, port_settings)
263
264             self.instance_settings = VmInstanceSettings(
265                 name=guid + '-vm_inst',
266                 flavor=self.flavor_creator.flavor_settings.name,
267                 port_settings=[port_settings])
268         except:
269             self.tearDown()
270             raise
271
272     def tearDown(self):
273         """
274         Cleanup deployed resources
275         :return:
276         """
277         if self.vm_inst:
278             try:
279                 nova_utils.delete_vm_instance(self.nova, self.vm_inst)
280             except:
281                 pass
282         if self.port:
283             try:
284                 neutron_utils.delete_port(self.neutron, self.port)
285             except:
286                 pass
287         if self.flavor_creator:
288             try:
289                 self.flavor_creator.clean()
290             except:
291                 pass
292         if self.network_creator:
293             try:
294                 self.network_creator.clean()
295             except:
296                 pass
297         if self.image_creator:
298             try:
299                 self.image_creator.clean()
300             except:
301                 pass
302
303     def test_create_instance(self):
304         """
305         Tests the nova_utils.create_server() method
306         :return:
307         """
308
309         self.vm_inst = nova_utils.create_server(
310             self.nova, self.neutron, self.glance, self.instance_settings,
311             self.image_creator.image_settings)
312
313         self.assertIsNotNone(self.vm_inst)
314
315         # Wait until instance is ACTIVE
316         iters = 0
317         active = False
318         while iters < 60:
319             if create_instance.STATUS_ACTIVE == nova_utils.get_server_status(
320                     self.nova, self.vm_inst):
321                 active = True
322                 break
323
324             time.sleep(3)
325             iters += 1
326
327         self.assertTrue(active)
328         vm_inst = nova_utils.get_latest_server_object(self.nova, self.vm_inst)
329
330         self.assertEqual(self.vm_inst.name, vm_inst.name)
331         self.assertEqual(self.vm_inst.id, vm_inst.id)