summaryrefslogtreecommitdiffstats
path: root/snaps/openstack/utils/nova_utils.py
blob: 9d0f70fa74e9b52a55aa45c1acebcea0bef3f699 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# Copyright (c) 2016 Cable Television Laboratories, Inc. ("CableLabs")
#                    and others.  All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import logging
import keystone_utils

from novaclient.client import Client
from novaclient.exceptions import NotFound

__author__ = 'spisarski'

logger = logging.getLogger('nova_utils')

"""
Utilities for basic OpenStack Nova API calls
"""


def nova_client(os_creds):
    """
    Instantiates and returns a client for communications with OpenStack's Nova server
    :param os_creds: The connection credentials to the OpenStack API
    :return: the client object
    """
    logger.debug('Retrieving Nova Client')
    return Client(os_creds.compute_api_version, session=keystone_utils.keystone_session(os_creds))


def get_servers_by_name(nova, name):
    """
    Returns a list of servers with a given name
    :param nova: the Nova client
    :param name: the server name
    :return: the list of servers
    """
    return nova.servers.list(search_opts={'name': name})


def get_latest_server_object(nova, server):
    """
    Returns a server with a given id
    :param nova: the Nova client
    :param server: the old server object
    :return: the list of servers or None if not found
    """
    return nova.servers.get(server)


def save_keys_to_files(keys=None, pub_file_path=None, priv_file_path=None):
    """
    Saves the generated RSA generated keys to the filesystem
    :param keys: the keys to save
    :param pub_file_path: the path to the public keys
    :param priv_file_path: the path to the private keys
    :return: None
    """
    if keys:
        if pub_file_path:
            pub_dir = os.path.dirname(pub_file_path)
            if not os.path.isdir(pub_dir):
                os.mkdir(pub_dir)
            public_handle = open(pub_file_path, 'wb')
            public_handle.write(keys.publickey().exportKey('OpenSSH'))
            public_handle.close()
            os.chmod(pub_file_path, 0o400)
            logger.info("Saved public key to - " + pub_file_path)
        if priv_file_path:
            priv_dir = os.path.dirname(priv_file_path)
            if not os.path.isdir(priv_dir):
                os.mkdir(priv_dir)
            private_handle = open(priv_file_path, 'wb')
            private_handle.write(keys.exportKey())
            private_handle.close()
            os.chmod(priv_file_path, 0o400)
            logger.info("Saved private key to - " + priv_file_path)


def upload_keypair_file(nova, name, file_path):
    """
    Uploads a public key from a file
    :param nova: the Nova client
    :param name: the keypair name
    :param file_path: the path to the public key file
    :return: the keypair object
    """
    with open(os.path.expanduser(file_path)) as fpubkey:
        logger.info('Saving keypair to - ' + file_path)
        return upload_keypair(nova, name, fpubkey.read())


def upload_keypair(nova, name, key):
    """
    Uploads a public key from a file
    :param nova: the Nova client
    :param name: the keypair name
    :param key: the public key object
    :return: the keypair object
    """
    logger.info('Creating keypair with name - ' + name)
    return nova.keypairs.create(name=name, public_key=key)


def keypair_exists(nova, keypair_obj):
    """
    Returns a copy of the keypair object if found
    :param nova: the Nova client
    :param keypair_obj: the keypair object
    :return: the keypair object or None if not found
    """
    try:
        return nova.keypairs.get(keypair_obj)
    except:
        return None


def get_keypair_by_name(nova, name):
    """
    Returns a list of all available keypairs
    :param nova: the Nova client
    :param name: the name of the keypair to lookup
    :return: the keypair object or None if not found
    """
    keypairs = nova.keypairs.list()

    for keypair in keypairs:
        if keypair.name == name:
            return keypair

    return None


def delete_keypair(nova, key):
    """
    Deletes a keypair object from OpenStack
    :param nova: the Nova client
    :param key: the keypair object to delete
    """
    logger.debug('Deleting keypair - ' + key.name)
    nova.keypairs.delete(key)


def get_floating_ip_pools(nova):
    """
    Returns all of the available floating IP pools
    :param nova: the Nova client
    :return: a list of pools
    """
    return nova.floating_ip_pools.list()


def get_floating_ips(nova):
    """
    Returns all of the floating IPs
    :param nova: the Nova client
    :return: a list of floating IPs
    """
    return nova.floating_ips.list()


def create_floating_ip(nova, ext_net_name):
    """
    Returns the floating IP object that was created with this call
    :param nova: the Nova client
    :param ext_net_name: the name of the external network on which to apply the floating IP address
    :return: the floating IP object
    """
    logger.info('Creating floating ip to external network - ' + ext_net_name)
    return nova.floating_ips.create(ext_net_name)


def get_floating_ip(nova, floating_ip):
    """
    Returns a floating IP object that should be identical to the floating_ip parameter
    :param nova: the Nova client
    :param floating_ip: the floating IP object to lookup
    :return: hopefully the same floating IP object input
    """
    logger.debug('Attempting to retrieve existing floating ip with IP - ' + floating_ip.ip)
    return nova.floating_ips.get(floating_ip)


def delete_floating_ip(nova, floating_ip):
    """
    Responsible for deleting a floating IP
    :param nova: the Nova client
    :param floating_ip: the floating IP object to delete
    :return:
    """
    logger.debug('Attempting to delete existing floating ip with IP - ' + floating_ip.ip)
    return nova.floating_ips.delete(floating_ip)


def get_nova_availability_zones(nova):
    """
    Returns the names of all nova compute servers
    :param nova: the Nova client
    :return: a list of compute server names
    """
    out = list()
    zones = nova.availability_zones.list()
    for zone in zones:
        if zone.zoneName == 'nova':
            for key, host in zone.hosts.iteritems():
                out.append(zone.zoneName + ':' + key)

    return out


def delete_vm_instance(nova, vm_inst):
    """
    Deletes a VM instance
    :param nova: the nova client
    :param vm_inst: the OpenStack instance object to delete
    """
    nova.servers.delete(vm_inst)


def get_flavor_by_name(nova, name):
    """
    Returns a flavor by name
    :param nova: the Nova client
    :param name: the flavor name to return
    :return: the OpenStack flavor object or None if not exists
    """
    try:
        return nova.flavors.find(name=name)
    except NotFound:
        return None


def create_flavor(nova, flavor_settings):
    """
    Creates and returns and OpenStack flavor object
    :param nova: the Nova client
    :param flavor_settings: the flavor settings
    :return: the Flavor
    """
    return nova.flavors.create(name=flavor_settings.name, flavorid=flavor_settings.flavor_id, ram=flavor_settings.ram,
                               vcpus=flavor_settings.vcpus, disk=flavor_settings.disk,
                               ephemeral=flavor_settings.ephemeral, swap=flavor_settings.swap,
                               rxtx_factor=flavor_settings.rxtx_factor, is_public=flavor_settings.is_public)


def delete_flavor(nova, flavor):
    """
    Deletes a flavor
    :param nova: the Nova client
    :param flavor: the OpenStack flavor object
    """
    nova.flavors.delete(flavor)


def add_security_group(nova, vm, security_group_name):
    """
    Adds a security group to an existing VM
    :param nova: the nova client
    :param vm: the OpenStack server object (VM) to alter
    :param security_group_name: the name of the security group to add
    """
    nova.servers.add_security_group(vm.id, security_group_name)


def remove_security_group(nova, vm, security_group):
    """
    Removes a security group from an existing VM
    :param nova: the nova client
    :param vm: the OpenStack server object (VM) to alter
    :param security_group: the OpenStack security group object to add
    """
    nova.servers.remove_security_group(vm.id, security_group)