9d0f70fa74e9b52a55aa45c1acebcea0bef3f699
[snaps.git] / snaps / openstack / utils / nova_utils.py
1 # Copyright (c) 2016 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 os
16 import logging
17 import keystone_utils
18
19 from novaclient.client import Client
20 from novaclient.exceptions import NotFound
21
22 __author__ = 'spisarski'
23
24 logger = logging.getLogger('nova_utils')
25
26 """
27 Utilities for basic OpenStack Nova API calls
28 """
29
30
31 def nova_client(os_creds):
32     """
33     Instantiates and returns a client for communications with OpenStack's Nova server
34     :param os_creds: The connection credentials to the OpenStack API
35     :return: the client object
36     """
37     logger.debug('Retrieving Nova Client')
38     return Client(os_creds.compute_api_version, session=keystone_utils.keystone_session(os_creds))
39
40
41 def get_servers_by_name(nova, name):
42     """
43     Returns a list of servers with a given name
44     :param nova: the Nova client
45     :param name: the server name
46     :return: the list of servers
47     """
48     return nova.servers.list(search_opts={'name': name})
49
50
51 def get_latest_server_object(nova, server):
52     """
53     Returns a server with a given id
54     :param nova: the Nova client
55     :param server: the old server object
56     :return: the list of servers or None if not found
57     """
58     return nova.servers.get(server)
59
60
61 def save_keys_to_files(keys=None, pub_file_path=None, priv_file_path=None):
62     """
63     Saves the generated RSA generated keys to the filesystem
64     :param keys: the keys to save
65     :param pub_file_path: the path to the public keys
66     :param priv_file_path: the path to the private keys
67     :return: None
68     """
69     if keys:
70         if pub_file_path:
71             pub_dir = os.path.dirname(pub_file_path)
72             if not os.path.isdir(pub_dir):
73                 os.mkdir(pub_dir)
74             public_handle = open(pub_file_path, 'wb')
75             public_handle.write(keys.publickey().exportKey('OpenSSH'))
76             public_handle.close()
77             os.chmod(pub_file_path, 0o400)
78             logger.info("Saved public key to - " + pub_file_path)
79         if priv_file_path:
80             priv_dir = os.path.dirname(priv_file_path)
81             if not os.path.isdir(priv_dir):
82                 os.mkdir(priv_dir)
83             private_handle = open(priv_file_path, 'wb')
84             private_handle.write(keys.exportKey())
85             private_handle.close()
86             os.chmod(priv_file_path, 0o400)
87             logger.info("Saved private key to - " + priv_file_path)
88
89
90 def upload_keypair_file(nova, name, file_path):
91     """
92     Uploads a public key from a file
93     :param nova: the Nova client
94     :param name: the keypair name
95     :param file_path: the path to the public key file
96     :return: the keypair object
97     """
98     with open(os.path.expanduser(file_path)) as fpubkey:
99         logger.info('Saving keypair to - ' + file_path)
100         return upload_keypair(nova, name, fpubkey.read())
101
102
103 def upload_keypair(nova, name, key):
104     """
105     Uploads a public key from a file
106     :param nova: the Nova client
107     :param name: the keypair name
108     :param key: the public key object
109     :return: the keypair object
110     """
111     logger.info('Creating keypair with name - ' + name)
112     return nova.keypairs.create(name=name, public_key=key)
113
114
115 def keypair_exists(nova, keypair_obj):
116     """
117     Returns a copy of the keypair object if found
118     :param nova: the Nova client
119     :param keypair_obj: the keypair object
120     :return: the keypair object or None if not found
121     """
122     try:
123         return nova.keypairs.get(keypair_obj)
124     except:
125         return None
126
127
128 def get_keypair_by_name(nova, name):
129     """
130     Returns a list of all available keypairs
131     :param nova: the Nova client
132     :param name: the name of the keypair to lookup
133     :return: the keypair object or None if not found
134     """
135     keypairs = nova.keypairs.list()
136
137     for keypair in keypairs:
138         if keypair.name == name:
139             return keypair
140
141     return None
142
143
144 def delete_keypair(nova, key):
145     """
146     Deletes a keypair object from OpenStack
147     :param nova: the Nova client
148     :param key: the keypair object to delete
149     """
150     logger.debug('Deleting keypair - ' + key.name)
151     nova.keypairs.delete(key)
152
153
154 def get_floating_ip_pools(nova):
155     """
156     Returns all of the available floating IP pools
157     :param nova: the Nova client
158     :return: a list of pools
159     """
160     return nova.floating_ip_pools.list()
161
162
163 def get_floating_ips(nova):
164     """
165     Returns all of the floating IPs
166     :param nova: the Nova client
167     :return: a list of floating IPs
168     """
169     return nova.floating_ips.list()
170
171
172 def create_floating_ip(nova, ext_net_name):
173     """
174     Returns the floating IP object that was created with this call
175     :param nova: the Nova client
176     :param ext_net_name: the name of the external network on which to apply the floating IP address
177     :return: the floating IP object
178     """
179     logger.info('Creating floating ip to external network - ' + ext_net_name)
180     return nova.floating_ips.create(ext_net_name)
181
182
183 def get_floating_ip(nova, floating_ip):
184     """
185     Returns a floating IP object that should be identical to the floating_ip parameter
186     :param nova: the Nova client
187     :param floating_ip: the floating IP object to lookup
188     :return: hopefully the same floating IP object input
189     """
190     logger.debug('Attempting to retrieve existing floating ip with IP - ' + floating_ip.ip)
191     return nova.floating_ips.get(floating_ip)
192
193
194 def delete_floating_ip(nova, floating_ip):
195     """
196     Responsible for deleting a floating IP
197     :param nova: the Nova client
198     :param floating_ip: the floating IP object to delete
199     :return:
200     """
201     logger.debug('Attempting to delete existing floating ip with IP - ' + floating_ip.ip)
202     return nova.floating_ips.delete(floating_ip)
203
204
205 def get_nova_availability_zones(nova):
206     """
207     Returns the names of all nova compute servers
208     :param nova: the Nova client
209     :return: a list of compute server names
210     """
211     out = list()
212     zones = nova.availability_zones.list()
213     for zone in zones:
214         if zone.zoneName == 'nova':
215             for key, host in zone.hosts.iteritems():
216                 out.append(zone.zoneName + ':' + key)
217
218     return out
219
220
221 def delete_vm_instance(nova, vm_inst):
222     """
223     Deletes a VM instance
224     :param nova: the nova client
225     :param vm_inst: the OpenStack instance object to delete
226     """
227     nova.servers.delete(vm_inst)
228
229
230 def get_flavor_by_name(nova, name):
231     """
232     Returns a flavor by name
233     :param nova: the Nova client
234     :param name: the flavor name to return
235     :return: the OpenStack flavor object or None if not exists
236     """
237     try:
238         return nova.flavors.find(name=name)
239     except NotFound:
240         return None
241
242
243 def create_flavor(nova, flavor_settings):
244     """
245     Creates and returns and OpenStack flavor object
246     :param nova: the Nova client
247     :param flavor_settings: the flavor settings
248     :return: the Flavor
249     """
250     return nova.flavors.create(name=flavor_settings.name, flavorid=flavor_settings.flavor_id, ram=flavor_settings.ram,
251                                vcpus=flavor_settings.vcpus, disk=flavor_settings.disk,
252                                ephemeral=flavor_settings.ephemeral, swap=flavor_settings.swap,
253                                rxtx_factor=flavor_settings.rxtx_factor, is_public=flavor_settings.is_public)
254
255
256 def delete_flavor(nova, flavor):
257     """
258     Deletes a flavor
259     :param nova: the Nova client
260     :param flavor: the OpenStack flavor object
261     """
262     nova.flavors.delete(flavor)
263
264
265 def add_security_group(nova, vm, security_group_name):
266     """
267     Adds a security group to an existing VM
268     :param nova: the nova client
269     :param vm: the OpenStack server object (VM) to alter
270     :param security_group_name: the name of the security group to add
271     """
272     nova.servers.add_security_group(vm.id, security_group_name)
273
274
275 def remove_security_group(nova, vm, security_group):
276     """
277     Removes a security group from an existing VM
278     :param nova: the nova client
279     :param vm: the OpenStack server object (VM) to alter
280     :param security_group: the OpenStack security group object to add
281     """
282     nova.servers.remove_security_group(vm.id, security_group)