summaryrefslogtreecommitdiffstats
path: root/snaps/openstack/utils/settings_utils.py
blob: 7f00075ada227083329281fd4cf9690264e12e9a (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
# Copyright (c) 2017 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 uuid

from snaps import file_utils
from snaps.openstack.create_instance import (
    VmInstanceSettings, FloatingIpSettings)
from snaps.openstack.create_keypairs import KeypairSettings
from snaps.openstack.create_network import (
    PortSettings, SubnetSettings, NetworkSettings)
from snaps.openstack.utils import (
    neutron_utils, nova_utils, heat_utils, glance_utils)


def create_network_settings(neutron, network):
    """
    Returns a NetworkSettings object
    :param neutron: the neutron client
    :param network: a SNAPS-OO Network domain object
    :return:
    """
    return NetworkSettings(
        name=network.name, network_type=network.type,
        subnet_settings=create_subnet_settings(neutron, network))


def create_subnet_settings(neutron, network):
    """
    Returns a list of SubnetSettings objects for a given network
    :param neutron: the OpenStack neutron client
    :param network: the SNAPS-OO Network domain object
    :return: a list
    """
    out = list()

    subnets = neutron_utils.get_subnets_by_network(neutron, network)
    for subnet in subnets:
        kwargs = dict()
        kwargs['cidr'] = subnet.cidr
        kwargs['ip_version'] = subnet.ip_version
        kwargs['name'] = subnet.name
        kwargs['start'] = subnet.start
        kwargs['end'] = subnet.end
        kwargs['gateway_ip'] = subnet.gateway_ip
        kwargs['enable_dhcp'] = subnet.enable_dhcp
        kwargs['dns_nameservers'] = subnet.dns_nameservers
        kwargs['host_routes'] = subnet.host_routes
        kwargs['ipv6_ra_mode'] = subnet.ipv6_ra_mode
        kwargs['ipv6_address_mode'] = subnet.ipv6_address_mode
        out.append(SubnetSettings(**kwargs))
    return out


def create_vm_inst_settings(nova, neutron, server):
    """
    Returns a NetworkSettings object
    :param nova: the nova client
    :param neutron: the neutron client
    :param server: a SNAPS-OO VmInst domain object
    :return:
    """

    flavor_name = nova_utils.get_flavor_by_id(nova, server.flavor_id)

    kwargs = dict()
    kwargs['name'] = server.name
    kwargs['flavor'] = flavor_name
    kwargs['port_settings'] = __create_port_settings(
        neutron, server.networks)
    kwargs['security_group_names'] = server.sec_grp_names
    kwargs['floating_ip_settings'] = __create_floatingip_settings(
        neutron, kwargs['port_settings'])

    return VmInstanceSettings(**kwargs)


def __create_port_settings(neutron, networks):
    """
    Returns a list of port settings based on the networks parameter
    :param neutron: the neutron client
    :param networks: a dict where the key is the network name and the value
                     is a list of IP addresses
    :return:
    """
    out = list()

    for net_name, ips in networks.items():
        network = neutron_utils.get_network(neutron, network_name=net_name)
        ports = neutron_utils.get_ports(neutron, network, ips)
        for port in ports:
            kwargs = dict()
            if port.name:
                kwargs['name'] = port.name
            kwargs['network_name'] = network.name
            kwargs['mac_address'] = port.mac_address
            kwargs['allowed_address_pairs'] = port.allowed_address_pairs
            kwargs['admin_state_up'] = port.admin_state_up
            out.append(PortSettings(**kwargs))

    return out


def __create_floatingip_settings(neutron, port_settings):
    """
    Returns a list of FloatingIPSettings objects as they pertain to an
    existing deployed server instance
    :param neutron: the neutron client
    :param port_settings: list of SNAPS-OO PortSettings objects
    :return: a list of FloatingIPSettings objects or an empty list if no
             floating IPs have been created
    """
    base_fip_name = 'fip-'
    fip_ctr = 1
    out = list()

    fip_ports = list()
    for port_setting in port_settings:
        setting_port = neutron_utils.get_port(neutron, port_setting)
        if setting_port:
            network = neutron_utils.get_network(
                neutron, network_name=port_setting.network_name)
            network_ports = neutron_utils.get_ports(neutron, network)
            if network_ports:
                for setting_port in network_ports:
                    if port_setting.mac_address == setting_port.mac_address:
                        fip_ports.append((port_setting.name, setting_port))
                        break

    floating_ips = neutron_utils.get_floating_ips(neutron, fip_ports)

    for port_id, floating_ip in floating_ips:
        router = neutron_utils.get_router_by_id(neutron, floating_ip.router_id)
        setting_port = neutron_utils.get_port_by_id(
            neutron, floating_ip.port_id)
        kwargs = dict()
        kwargs['name'] = base_fip_name + str(fip_ctr)
        kwargs['port_name'] = setting_port.name
        kwargs['port_id'] = setting_port.id
        kwargs['router_name'] = router.name

        if setting_port:
            for ip_dict in setting_port.ips:
                if ('ip_address' in ip_dict and
                        'subnet_id' in ip_dict and
                        ip_dict['ip_address'] == floating_ip.fixed_ip_address):
                    subnet = neutron_utils.get_subnet_by_id(
                        neutron, ip_dict['subnet_id'])
                    if subnet:
                        kwargs['subnet_name'] = subnet.name

        out.append(FloatingIpSettings(**kwargs))

        fip_ctr += 1

    return out


def determine_image_settings(glance, server, image_settings):
    """
    Returns a ImageSettings object from the list that matches the name in one
    of the image_settings parameter
    :param glance: the glance client
    :param server: a SNAPS-OO VmInst domain object
    :param image_settings: list of ImageSettings objects
    :return: ImageSettings or None
    """
    if image_settings:
        for image_setting in image_settings:
            image = glance_utils.get_image_by_id(glance, server.image_id)
            if image and image.name == image_setting.name:
                return image_setting


def determine_keypair_settings(heat_cli, stack, server, keypair_settings=None,
                               priv_key_key=None):
    """
    Returns a KeypairSettings object from the list that matches the
    server.keypair_name value in the keypair_settings parameter if not None,
    else if the output_key is not None, the output's value when contains the
    string 'BEGIN RSA PRIVATE KEY', this value will be stored into a file and
    encoded into the KeypairSettings object returned
    :param heat_cli: the OpenStack heat client
    :param stack: a SNAPS-OO Stack domain object
    :param server: a SNAPS-OO VmInst domain object
    :param keypair_settings: list of KeypairSettings objects
    :param priv_key_key: the stack options that holds the private key value
    :return: KeypairSettings or None
    """
    # Existing keypair being used by Heat Template
    if keypair_settings:
        for keypair_setting in keypair_settings:
            if server.keypair_name == keypair_setting.name:
                return keypair_setting

    # Keypair created by Heat template
    if priv_key_key:
        outputs = heat_utils.get_outputs(heat_cli, stack)
        for output in outputs:
            if output.key == priv_key_key:
                # Save to file
                guid = uuid.uuid4()
                key_file = file_utils.save_string_to_file(
                    output.value, str(guid), 0o400)

                # Use outputs, file and resources for the KeypairSettings
                return KeypairSettings(
                    name=server.keypair_name, private_filepath=key_file.name)