1 # Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
2 # and others. All rights reserved.
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:
8 # http://www.apache.org/licenses/LICENSE-2.0
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 from snaps.config.network import PortConfig
18 class VmInstanceConfig(object):
20 Class responsible for holding configuration setting for a VM Instance
23 def __init__(self, **kwargs):
26 :param name: the name of the VM
27 :param flavor: the VM's flavor name
28 :param port_settings: the port configuration settings (required)
29 :param security_group_names: a set of names of the security groups to
31 :param floating_ip_settings: the floating IP configuration settings
32 :param sudo_user: the sudo user of the VM that will override the
33 instance_settings.image_user when trying to
35 :param vm_boot_timeout: the amount of time a thread will sleep waiting
36 for an instance to boot
37 :param vm_delete_timeout: the amount of time a thread will sleep
38 waiting for an instance to be deleted
39 :param ssh_connect_timeout: the amount of time a thread will sleep
40 waiting obtaining an SSH connection to a VM
41 :param availability_zone: the name of the compute server on which to
42 deploy the VM (optional)
43 :param volume_names: a list of the names of the volume to attach
45 :param userdata: the string contents of any optional cloud-init script
46 to execute after the VM has been activated.
47 This value may also contain a dict who's key value
48 must contain the key 'cloud-init_file' which denotes
49 the location of some file containing the cloud-init
52 self.name = kwargs.get('name')
53 self.flavor = kwargs.get('flavor')
54 self.sudo_user = kwargs.get('sudo_user')
55 self.userdata = kwargs.get('userdata')
57 self.port_settings = list()
58 port_settings = kwargs.get('ports')
60 port_settings = kwargs.get('port_settings')
62 for port_setting in port_settings:
63 if isinstance(port_setting, dict):
64 self.port_settings.append(PortConfig(**port_setting))
65 elif isinstance(port_setting, PortConfig):
66 self.port_settings.append(port_setting)
68 if kwargs.get('security_group_names'):
69 if isinstance(kwargs['security_group_names'], list):
70 self.security_group_names = kwargs['security_group_names']
71 elif isinstance(kwargs['security_group_names'], set):
72 self.security_group_names = kwargs['security_group_names']
73 elif isinstance(kwargs['security_group_names'], str):
74 self.security_group_names = [kwargs['security_group_names']]
76 raise VmInstanceConfigError(
77 'Invalid data type for security_group_names attribute')
79 self.security_group_names = set()
81 self.floating_ip_settings = list()
82 floating_ip_settings = kwargs.get('floating_ips')
83 if not floating_ip_settings:
84 floating_ip_settings = kwargs.get('floating_ip_settings')
85 if floating_ip_settings:
86 for floating_ip_config in floating_ip_settings:
87 if isinstance(floating_ip_config, FloatingIpConfig):
88 self.floating_ip_settings.append(floating_ip_config)
90 self.floating_ip_settings.append(FloatingIpConfig(
91 **floating_ip_config['floating_ip']))
93 self.vm_boot_timeout = kwargs.get('vm_boot_timeout', 900)
94 self.vm_delete_timeout = kwargs.get('vm_delete_timeout', 300)
95 self.ssh_connect_timeout = kwargs.get('ssh_connect_timeout', 180)
96 self.availability_zone = kwargs.get('availability_zone')
97 self.volume_names = kwargs.get('volume_names')
99 if self.volume_names and not isinstance(self.volume_names, list):
100 raise VmInstanceConfigError('volume_names must be a list')
102 if not self.name or not self.flavor:
103 raise VmInstanceConfigError(
104 'Instance configuration requires the attributes: name, flavor')
106 if len(self.port_settings) == 0:
107 raise VmInstanceConfigError(
108 'Instance configuration requires port settings (aka. NICS)')
111 class FloatingIpConfig(object):
113 Class responsible for holding configuration settings for a floating IP
116 def __init__(self, **kwargs):
119 :param name: the name of the floating IP
120 :param port_name: the name of the router to the external network
121 :param router_name: the name of the router to the external network
122 :param subnet_name: the name of the subnet on which to attach the
124 :param provisioning: when true, this floating IP can be used for
127 TODO - provisioning flag is a hack as I have only observed a single
128 Floating IPs that actually works on an instance. Multiple floating IPs
129 placed on different subnets from the same port are especially
130 troublesome as you cannot predict which one will actually connect.
131 For now, it is recommended not to setup multiple floating IPs on an
132 instance unless absolutely necessary.
134 self.name = kwargs.get('name')
135 self.port_name = kwargs.get('port_name')
136 self.port_id = kwargs.get('port_id')
137 self.router_name = kwargs.get('router_name')
138 self.subnet_name = kwargs.get('subnet_name')
139 if kwargs.get('provisioning') is not None:
140 self.provisioning = kwargs['provisioning']
142 self.provisioning = True
144 # if not self.name or not self.port_name or not self.router_name:
145 if not self.name or not self.router_name:
146 raise FloatingIpConfigError(
147 'The attributes name, port_name and router_name are required')
149 if not self.port_name and not self.port_id:
150 raise FloatingIpConfigError(
151 'The attributes port_name or port_id are required')
154 class VmInstanceConfigError(Exception):
156 Exception to be thrown when an VM instance settings are incorrect
160 class FloatingIpConfigError(Exception):
162 Exception to be thrown when an VM instance settings are incorrect