Second patch for volume support.
[snaps.git] / snaps / openstack / utils / settings_utils.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 uuid
16
17 from snaps import file_utils
18 from snaps.openstack.create_instance import (
19     VmInstanceSettings, FloatingIpSettings)
20 from snaps.openstack.create_keypairs import KeypairSettings
21 from snaps.openstack.create_network import (
22     PortSettings, SubnetSettings, NetworkSettings)
23 from snaps.openstack.utils import (
24     neutron_utils, nova_utils, heat_utils, glance_utils)
25
26
27 def create_network_settings(neutron, network):
28     """
29     Returns a NetworkSettings object
30     :param neutron: the neutron client
31     :param network: a SNAPS-OO Network domain object
32     :return:
33     """
34     return NetworkSettings(
35         name=network.name, network_type=network.type,
36         subnet_settings=create_subnet_settings(neutron, network))
37
38
39 def create_subnet_settings(neutron, network):
40     """
41     Returns a list of SubnetSettings objects for a given network
42     :param neutron: the OpenStack neutron client
43     :param network: the SNAPS-OO Network domain object
44     :return: a list
45     """
46     out = list()
47
48     subnets = neutron_utils.get_subnets_by_network(neutron, network)
49     for subnet in subnets:
50         kwargs = dict()
51         kwargs['cidr'] = subnet.cidr
52         kwargs['ip_version'] = subnet.ip_version
53         kwargs['name'] = subnet.name
54         kwargs['start'] = subnet.start
55         kwargs['end'] = subnet.end
56         kwargs['gateway_ip'] = subnet.gateway_ip
57         kwargs['enable_dhcp'] = subnet.enable_dhcp
58         kwargs['dns_nameservers'] = subnet.dns_nameservers
59         kwargs['host_routes'] = subnet.host_routes
60         kwargs['ipv6_ra_mode'] = subnet.ipv6_ra_mode
61         kwargs['ipv6_address_mode'] = subnet.ipv6_address_mode
62         out.append(SubnetSettings(**kwargs))
63     return out
64
65
66 def create_vm_inst_settings(nova, neutron, server):
67     """
68     Returns a NetworkSettings object
69     :param nova: the nova client
70     :param neutron: the neutron client
71     :param server: a SNAPS-OO VmInst domain object
72     :return:
73     """
74
75     flavor_name = nova_utils.get_flavor_by_id(nova, server.flavor_id)
76
77     kwargs = dict()
78     kwargs['name'] = server.name
79     kwargs['flavor'] = flavor_name
80     kwargs['port_settings'] = __create_port_settings(
81         neutron, server.networks)
82     kwargs['security_group_names'] = server.sec_grp_names
83     kwargs['floating_ip_settings'] = __create_floatingip_settings(
84         neutron, kwargs['port_settings'])
85
86     return VmInstanceSettings(**kwargs)
87
88
89 def __create_port_settings(neutron, networks):
90     """
91     Returns a list of port settings based on the networks parameter
92     :param neutron: the neutron client
93     :param networks: a dict where the key is the network name and the value
94                      is a list of IP addresses
95     :return:
96     """
97     out = list()
98
99     for net_name, ips in networks.items():
100         network = neutron_utils.get_network(neutron, network_name=net_name)
101         ports = neutron_utils.get_ports(neutron, network, ips)
102         for port in ports:
103             kwargs = dict()
104             if port.name:
105                 kwargs['name'] = port.name
106             kwargs['network_name'] = network.name
107             kwargs['mac_address'] = port.mac_address
108             kwargs['allowed_address_pairs'] = port.allowed_address_pairs
109             kwargs['admin_state_up'] = port.admin_state_up
110             out.append(PortSettings(**kwargs))
111
112     return out
113
114
115 def __create_floatingip_settings(neutron, port_settings):
116     """
117     Returns a list of FloatingIPSettings objects as they pertain to an
118     existing deployed server instance
119     :param neutron: the neutron client
120     :param port_settings: list of SNAPS-OO PortSettings objects
121     :return: a list of FloatingIPSettings objects or an empty list if no
122              floating IPs have been created
123     """
124     base_fip_name = 'fip-'
125     fip_ctr = 1
126     out = list()
127
128     fip_ports = list()
129     for port_setting in port_settings:
130         setting_port = neutron_utils.get_port(neutron, port_setting)
131         if setting_port:
132             network = neutron_utils.get_network(
133                 neutron, network_name=port_setting.network_name)
134             network_ports = neutron_utils.get_ports(neutron, network)
135             if network_ports:
136                 for setting_port in network_ports:
137                     if port_setting.mac_address == setting_port.mac_address:
138                         fip_ports.append((port_setting.name, setting_port))
139                         break
140
141     floating_ips = neutron_utils.get_floating_ips(neutron, fip_ports)
142
143     for port_id, floating_ip in floating_ips:
144         router = neutron_utils.get_router_by_id(neutron, floating_ip.router_id)
145         setting_port = neutron_utils.get_port_by_id(
146             neutron, floating_ip.port_id)
147         kwargs = dict()
148         kwargs['name'] = base_fip_name + str(fip_ctr)
149         kwargs['port_name'] = setting_port.name
150         kwargs['port_id'] = setting_port.id
151         kwargs['router_name'] = router.name
152
153         if setting_port:
154             for ip_dict in setting_port.ips:
155                 if ('ip_address' in ip_dict and
156                         'subnet_id' in ip_dict and
157                         ip_dict['ip_address'] == floating_ip.fixed_ip_address):
158                     subnet = neutron_utils.get_subnet_by_id(
159                         neutron, ip_dict['subnet_id'])
160                     if subnet:
161                         kwargs['subnet_name'] = subnet.name
162
163         out.append(FloatingIpSettings(**kwargs))
164
165         fip_ctr += 1
166
167     return out
168
169
170 def determine_image_settings(glance, server, image_settings):
171     """
172     Returns a ImageSettings object from the list that matches the name in one
173     of the image_settings parameter
174     :param glance: the glance client
175     :param server: a SNAPS-OO VmInst domain object
176     :param image_settings: list of ImageSettings objects
177     :return: ImageSettings or None
178     """
179     if image_settings:
180         for image_setting in image_settings:
181             image = glance_utils.get_image_by_id(glance, server.image_id)
182             if image and image.name == image_setting.name:
183                 return image_setting
184
185
186 def determine_keypair_settings(heat_cli, stack, server, keypair_settings=None,
187                                priv_key_key=None):
188     """
189     Returns a KeypairSettings object from the list that matches the
190     server.keypair_name value in the keypair_settings parameter if not None,
191     else if the output_key is not None, the output's value when contains the
192     string 'BEGIN RSA PRIVATE KEY', this value will be stored into a file and
193     encoded into the KeypairSettings object returned
194     :param heat_cli: the OpenStack heat client
195     :param stack: a SNAPS-OO Stack domain object
196     :param server: a SNAPS-OO VmInst domain object
197     :param keypair_settings: list of KeypairSettings objects
198     :param priv_key_key: the stack options that holds the private key value
199     :return: KeypairSettings or None
200     """
201     # Existing keypair being used by Heat Template
202     if keypair_settings:
203         for keypair_setting in keypair_settings:
204             if server.keypair_name == keypair_setting.name:
205                 return keypair_setting
206
207     # Keypair created by Heat template
208     if priv_key_key:
209         outputs = heat_utils.get_outputs(heat_cli, stack)
210         for output in outputs:
211             if output.key == priv_key_key:
212                 # Save to file
213                 guid = uuid.uuid4()
214                 key_file = file_utils.save_string_to_file(
215                     output.value, str(guid), 0o400)
216
217                 # Use outputs, file and resources for the KeypairSettings
218                 return KeypairSettings(
219                     name=server.keypair_name, private_filepath=key_file.name)