blob: db9a72adfad04dd8293c9cec187807f4a403050b [file] [log] [blame]
seryio34478552019-05-23 14:50:49 +02001# -*- coding: utf-8 -*-
jamartinezv14a823d2019-08-01 11:45:15 +02002import base64
3
lloretgalleg45220152019-10-29 11:53:49 +01004
5
seryio34478552019-05-23 14:50:49 +02006import vimconn
7import logging
tierno24620412019-06-03 14:05:08 +00008import netaddr
lloretgalleg45220152019-10-29 11:53:49 +01009import re
seryio34478552019-05-23 14:50:49 +020010
11from os import getenv
seryio34478552019-05-23 14:50:49 +020012from azure.common.credentials import ServicePrincipalCredentials
13from azure.mgmt.resource import ResourceManagementClient
14from azure.mgmt.network import NetworkManagementClient
15from azure.mgmt.compute import ComputeManagementClient
lloretgallegbfc28b02019-11-21 09:31:16 +010016from azure.mgmt.compute.models import DiskCreateOption
tierno84efdc12019-05-29 09:29:01 +000017from msrestazure.azure_exceptions import CloudError
lloretgalleg45220152019-10-29 11:53:49 +010018from msrest.exceptions import AuthenticationError
19from requests.exceptions import ConnectionError
20
21__author__ = 'Sergio Gonzalez'
22__date__ = '$18-apr-2019 23:59:59$'
23
tiernodeb74b22019-05-27 10:24:50 +000024
jamartinezv14a823d2019-08-01 11:45:15 +020025if getenv('OSMRO_PDB_DEBUG'):
26 import sys
27 print(sys.path)
28 import pdb
29 pdb.set_trace()
30
31
seryio34478552019-05-23 14:50:49 +020032class vimconnector(vimconn.vimconnector):
33
lloretgalleg45220152019-10-29 11:53:49 +010034 # Translate azure provisioning state to OSM provision state
35 # The first three ones are the transitional status once a user initiated action has been requested
36 # Once the operation is complete, it will transition into the states Succeeded or Failed
37 # https://docs.microsoft.com/en-us/azure/virtual-machines/windows/states-lifecycle
tierno84efdc12019-05-29 09:29:01 +000038 provision_state2osm = {
lloretgalleg45220152019-10-29 11:53:49 +010039 "Creating": "BUILD",
tierno84efdc12019-05-29 09:29:01 +000040 "Updating": "BUILD",
lloretgalleg45220152019-10-29 11:53:49 +010041 "Deleting": "INACTIVE",
42 "Succeeded": "ACTIVE",
43 "Failed": "ERROR"
44 }
45
46 # Translate azure power state to OSM provision state
47 power_state2osm = {
48 "starting": "INACTIVE",
49 "running": "ACTIVE",
50 "stopping": "INACTIVE",
51 "stopped": "INACTIVE",
52 "unknown": "OTHER",
53 "deallocated": "BUILD",
54 "deallocating": "BUILD"
tierno84efdc12019-05-29 09:29:01 +000055 }
56
seryio34478552019-05-23 14:50:49 +020057 def __init__(self, uuid, name, tenant_id, tenant_name, url, url_admin=None, user=None, passwd=None, log_level=None,
58 config={}, persistent_info={}):
lloretgalleg45220152019-10-29 11:53:49 +010059 """
60 Constructor of VIM. Raise an exception is some needed parameter is missing, but it must not do any connectivity
61 checking against the VIM
62 Using common constructor parameters.
63 In this case: config must include the following parameters:
64 subscription_id: assigned azure subscription identifier
65 region_name: current region for azure network
66 resource_group: used for all azure created resources
67 vnet_name: base vnet for azure, created networks will be subnets from this base network
68 config may also include the following parameter:
69 flavors_pattern: pattern that will be used to select a range of vm sizes, for example
70 "^((?!Standard_B).)*$" will filter out Standard_B range that is cheap but is very overused
71 "^Standard_B" will select a serie B maybe for test environment
72 """
seryio34478552019-05-23 14:50:49 +020073
74 vimconn.vimconnector.__init__(self, uuid, name, tenant_id, tenant_name, url, url_admin, user, passwd, log_level,
75 config, persistent_info)
76
lloretgalleg45220152019-10-29 11:53:49 +010077 # Variable that indicates if client must be reloaded or initialized
78 self.reload_client = True
79
tierno84efdc12019-05-29 09:29:01 +000080 self.vnet_address_space = None
seryio34478552019-05-23 14:50:49 +020081 # LOGGER
82 self.logger = logging.getLogger('openmano.vim.azure')
83 if log_level:
84 logging.basicConfig()
85 self.logger.setLevel(getattr(logging, log_level))
86
lloretgalleg45220152019-10-29 11:53:49 +010087 self.tenant = (tenant_id or tenant_name)
tierno30d0d6d2019-05-27 08:14:01 +000088
lloretgalleg45220152019-10-29 11:53:49 +010089 # Store config to create azure subscription later
90 self._config = {}
91 self._config["user"] = user
92 self._config["passwd"] = passwd
93 self._config["tenant"] = (tenant_id or tenant_name)
jamartinezv14a823d2019-08-01 11:45:15 +020094
tierno30d0d6d2019-05-27 08:14:01 +000095 # SUBSCRIPTION
seryio34478552019-05-23 14:50:49 +020096 if 'subscription_id' in config:
lloretgalleg45220152019-10-29 11:53:49 +010097 self._config["subscription_id"] = config.get('subscription_id')
98 #self.logger.debug('Setting subscription to: %s', self.config["subscription_id"])
seryio34478552019-05-23 14:50:49 +020099 else:
100 raise vimconn.vimconnException('Subscription not specified')
lloretgalleg45220152019-10-29 11:53:49 +0100101
tierno30d0d6d2019-05-27 08:14:01 +0000102 # REGION
seryio34478552019-05-23 14:50:49 +0200103 if 'region_name' in config:
104 self.region = config.get('region_name')
105 else:
106 raise vimconn.vimconnException('Azure region_name is not specified at config')
lloretgalleg45220152019-10-29 11:53:49 +0100107
tierno30d0d6d2019-05-27 08:14:01 +0000108 # RESOURCE_GROUP
seryio34478552019-05-23 14:50:49 +0200109 if 'resource_group' in config:
110 self.resource_group = config.get('resource_group')
111 else:
112 raise vimconn.vimconnException('Azure resource_group is not specified at config')
lloretgalleg45220152019-10-29 11:53:49 +0100113
seryio34478552019-05-23 14:50:49 +0200114 # VNET_NAME
115 if 'vnet_name' in config:
116 self.vnet_name = config["vnet_name"]
117
118 # public ssh key
119 self.pub_key = config.get('pub_key')
lloretgalleg45220152019-10-29 11:53:49 +0100120
121 # flavor pattern regex
122 if 'flavors_pattern' in config:
123 self._config['flavors_pattern'] = config['flavors_pattern']
seryio34478552019-05-23 14:50:49 +0200124
125 def _reload_connection(self):
tiernodeb74b22019-05-27 10:24:50 +0000126 """
lloretgalleg45220152019-10-29 11:53:49 +0100127 Called before any operation, checks python azure clients
tiernodeb74b22019-05-27 10:24:50 +0000128 """
lloretgalleg45220152019-10-29 11:53:49 +0100129 if self.reload_client:
130 self.logger.debug('reloading azure client')
131 try:
132 self.credentials = ServicePrincipalCredentials(
133 client_id=self._config["user"],
134 secret=self._config["passwd"],
135 tenant=self._config["tenant"]
136 )
137 self.conn = ResourceManagementClient(self.credentials, self._config["subscription_id"])
138 self.conn_compute = ComputeManagementClient(self.credentials, self._config["subscription_id"])
139 self.conn_vnet = NetworkManagementClient(self.credentials, self._config["subscription_id"])
140 self._check_or_create_resource_group()
141 self._check_or_create_vnet()
142
143 # Set to client created
144 self.reload_client = False
145 except Exception as e:
146 self._format_vimconn_exception(e)
seryio34478552019-05-23 14:50:49 +0200147
148 def _get_resource_name_from_resource_id(self, resource_id):
lloretgalleg45220152019-10-29 11:53:49 +0100149 """
150 Obtains resource_name from the azure complete identifier: resource_name will always be last item
151 """
jamartinezv14a823d2019-08-01 11:45:15 +0200152 try:
lloretgalleg45220152019-10-29 11:53:49 +0100153 resource = str(resource_id.split('/')[-1])
jamartinezv14a823d2019-08-01 11:45:15 +0200154 return resource
155 except Exception as e:
lloretgalleg45220152019-10-29 11:53:49 +0100156 raise vimconn.vimconnException("Unable to get resource name from invalid resource_id format: '{}'".format(resource_id))
seryio34478552019-05-23 14:50:49 +0200157
158 def _get_location_from_resource_group(self, resource_group_name):
jamartinezv14a823d2019-08-01 11:45:15 +0200159 try:
lloretgalleg45220152019-10-29 11:53:49 +0100160 location = self.conn.resource_groups.get(resource_group_name).location
jamartinezv14a823d2019-08-01 11:45:15 +0200161 return location
162 except Exception as e:
163 raise vimconn.vimconnNotFoundException("Location '{}' not found".format(resource_group_name))
164
seryio34478552019-05-23 14:50:49 +0200165 def _get_resource_group_name_from_resource_id(self, resource_id):
jamartinezv14a823d2019-08-01 11:45:15 +0200166
167 try:
lloretgalleg45220152019-10-29 11:53:49 +0100168 rg = str(resource_id.split('/')[4])
jamartinezv14a823d2019-08-01 11:45:15 +0200169 return rg
170 except Exception as e:
lloretgalleg45220152019-10-29 11:53:49 +0100171 raise vimconn.vimconnException("Unable to get resource group from invalid resource_id format '{}'".
172 format(resource_id))
jamartinezv14a823d2019-08-01 11:45:15 +0200173
174 def _get_net_name_from_resource_id(self, resource_id):
175
176 try:
lloretgalleg45220152019-10-29 11:53:49 +0100177 net_name = str(resource_id.split('/')[8])
jamartinezv14a823d2019-08-01 11:45:15 +0200178 return net_name
179 except Exception as e:
lloretgalleg45220152019-10-29 11:53:49 +0100180 raise vimconn.vimconnException("Unable to get azure net_name from invalid resource_id format '{}'".
181 format(resource_id))
seryio34478552019-05-23 14:50:49 +0200182
183 def _check_subnets_for_vm(self, net_list):
tierno30d0d6d2019-05-27 08:14:01 +0000184 # All subnets must belong to the same resource group and vnet
lloretgalleg45220152019-10-29 11:53:49 +0100185 rg_vnet = set(self._get_resource_group_name_from_resource_id(net['net_id']) +
186 self._get_net_name_from_resource_id(net['net_id']) for net in net_list)
jamartinezv14a823d2019-08-01 11:45:15 +0200187
lloretgalleg45220152019-10-29 11:53:49 +0100188 if len(rg_vnet) != 1:
189 raise self._format_vimconn_exception('Azure VMs can only attach to subnets in same VNET')
seryio34478552019-05-23 14:50:49 +0200190
lloretgalleg45220152019-10-29 11:53:49 +0100191 def _format_vimconn_exception(self, e):
tiernodeb74b22019-05-27 10:24:50 +0000192 """
lloretgalleg45220152019-10-29 11:53:49 +0100193 Transforms a generic or azure exception to a vimcommException
tiernodeb74b22019-05-27 10:24:50 +0000194 """
lloretgalleg45220152019-10-29 11:53:49 +0100195 if isinstance(e, vimconn.vimconnException):
196 raise
197 elif isinstance(e, AuthenticationError):
198 raise vimconn.vimconnAuthException(type(e).__name__ + ': ' + str(e))
199 elif isinstance(e, ConnectionError):
200 raise vimconn.vimconnConnectionException(type(e).__name__ + ': ' + str(e))
201 else:
202 # In case of generic error recreate client
203 self.reload_client = True
204 raise vimconn.vimconnException(type(e).__name__ + ': ' + str(e))
seryio34478552019-05-23 14:50:49 +0200205
206 def _check_or_create_resource_group(self):
tiernodeb74b22019-05-27 10:24:50 +0000207 """
lloretgalleg45220152019-10-29 11:53:49 +0100208 Creates the base resource group if it does not exist
tiernodeb74b22019-05-27 10:24:50 +0000209 """
lloretgalleg45220152019-10-29 11:53:49 +0100210 try:
211 rg_exists = self.conn.resource_groups.check_existence(self.resource_group)
212 if not rg_exists:
213 self.logger.debug("create base rgroup: %s", self.resource_group)
214 self.conn.resource_groups.create_or_update(self.resource_group, {'location': self.region})
215 except Exception as e:
216 self._format_vimconn_exception(e)
tiernodeb74b22019-05-27 10:24:50 +0000217
218 def _check_or_create_vnet(self):
lloretgalleg45220152019-10-29 11:53:49 +0100219 """
220 Try to get existent base vnet, in case it does not exist it creates it
221 """
tiernodeb74b22019-05-27 10:24:50 +0000222 try:
tierno84efdc12019-05-29 09:29:01 +0000223 vnet = self.conn_vnet.virtual_networks.get(self.resource_group, self.vnet_name)
224 self.vnet_address_space = vnet.address_space.address_prefixes[0]
tierno24620412019-06-03 14:05:08 +0000225 self.vnet_id = vnet.id
tierno84efdc12019-05-29 09:29:01 +0000226 return
227 except CloudError as e:
lloretgalleg45220152019-10-29 11:53:49 +0100228 if e.error.error and "notfound" in e.error.error.lower():
tierno84efdc12019-05-29 09:29:01 +0000229 pass
lloretgalleg45220152019-10-29 11:53:49 +0100230 # continue and create it
tierno84efdc12019-05-29 09:29:01 +0000231 else:
lloretgalleg45220152019-10-29 11:53:49 +0100232 self._format_vimconn_exception(e)
233
234 # if it does not exist, create it
tierno84efdc12019-05-29 09:29:01 +0000235 try:
tiernodeb74b22019-05-27 10:24:50 +0000236 vnet_params = {
237 'location': self.region,
238 'address_space': {
tierno84efdc12019-05-29 09:29:01 +0000239 'address_prefixes': ["10.0.0.0/8"]
tiernodeb74b22019-05-27 10:24:50 +0000240 },
241 }
tierno84efdc12019-05-29 09:29:01 +0000242 self.vnet_address_space = "10.0.0.0/8"
jamartinezv14a823d2019-08-01 11:45:15 +0200243
lloretgalleg45220152019-10-29 11:53:49 +0100244 self.logger.debug("create base vnet: %s", self.vnet_name)
tiernodeb74b22019-05-27 10:24:50 +0000245 self.conn_vnet.virtual_networks.create_or_update(self.resource_group, self.vnet_name, vnet_params)
tierno24620412019-06-03 14:05:08 +0000246 vnet = self.conn_vnet.virtual_networks.get(self.resource_group, self.vnet_name)
247 self.vnet_id = vnet.id
tiernodeb74b22019-05-27 10:24:50 +0000248 except Exception as e:
lloretgalleg45220152019-10-29 11:53:49 +0100249 self._format_vimconn_exception(e)
seryio34478552019-05-23 14:50:49 +0200250
251 def new_network(self, net_name, net_type, ip_profile=None, shared=False, vlan=None):
tiernodeb74b22019-05-27 10:24:50 +0000252 """
253 Adds a tenant network to VIM
254 :param net_name: name of the network
lloretgalleg45220152019-10-29 11:53:49 +0100255 :param net_type: not used for azure networks
tiernodeb74b22019-05-27 10:24:50 +0000256 :param ip_profile: is a dict containing the IP parameters of the network (Currently only IPv4 is implemented)
seryio34478552019-05-23 14:50:49 +0200257 'ip-version': can be one of ['IPv4','IPv6']
258 'subnet-address': ip_prefix_schema, that is X.X.X.X/Y
lloretgalleg45220152019-10-29 11:53:49 +0100259 'gateway-address': (Optional) ip_schema, that is X.X.X.X, not implemented for azure connector
260 'dns-address': (Optional) ip_schema, not implemented for azure connector
261 'dhcp': (Optional) dict containing, not implemented for azure connector
seryio34478552019-05-23 14:50:49 +0200262 'enabled': {'type': 'boolean'},
263 'start-address': ip_schema, first IP to grant
264 'count': number of IPs to grant.
lloretgalleg45220152019-10-29 11:53:49 +0100265 :param shared: Not allowed for Azure Connector
266 :param vlan: VLAN tagging is not allowed for Azure
tiernodeb74b22019-05-27 10:24:50 +0000267 :return: a tuple with the network identifier and created_items, or raises an exception on error
seryio34478552019-05-23 14:50:49 +0200268 created_items can be None or a dictionary where this method can include key-values that will be passed to
269 the method delete_network. Can be used to store created segments, created l2gw connections, etc.
270 Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same
271 as not present.
tiernodeb74b22019-05-27 10:24:50 +0000272 """
seryio34478552019-05-23 14:50:49 +0200273 return self._new_subnet(net_name, ip_profile)
274
275 def _new_subnet(self, net_name, ip_profile):
tiernodeb74b22019-05-27 10:24:50 +0000276 """
lloretgalleg45220152019-10-29 11:53:49 +0100277 Adds a tenant network to VIM. It creates a new subnet at existing base vnet
278 :param net_name: subnet name
tiernodeb74b22019-05-27 10:24:50 +0000279 :param ip_profile:
lloretgalleg45220152019-10-29 11:53:49 +0100280 subnet-address: if it is not provided a subnet/24 in the default vnet is created,
281 otherwise it creates a subnet in the indicated address
282 :return: a tuple with the network identifier and created_items, or raises an exception on error
tiernodeb74b22019-05-27 10:24:50 +0000283 """
lloretgalleg45220152019-10-29 11:53:49 +0100284 self.logger.debug('create subnet name %s, ip_profile %s', net_name, ip_profile)
seryio34478552019-05-23 14:50:49 +0200285 self._reload_connection()
seryio34478552019-05-23 14:50:49 +0200286
287 if ip_profile is None:
tierno24620412019-06-03 14:05:08 +0000288 # get a non used vnet ip range /24 and allocate automatically inside the range self.vnet_address_space
289 used_subnets = self.get_network_list()
290 for ip_range in netaddr.IPNetwork(self.vnet_address_space).subnet(24):
291 for used_subnet in used_subnets:
292 subnet_range = netaddr.IPNetwork(used_subnet["cidr_block"])
293 if subnet_range in ip_range or ip_range in subnet_range:
294 # this range overlaps with an existing subnet ip range. Breaks and look for another
295 break
296 else:
297 ip_profile = {"subnet_address": str(ip_range)}
lloretgalleg45220152019-10-29 11:53:49 +0100298 self.logger.debug('dinamically obtained ip_profile: %s', ip_range)
tierno24620412019-06-03 14:05:08 +0000299 break
300 else:
lloretgalleg45220152019-10-29 11:53:49 +0100301 raise vimconn.vimconnException("Cannot find a non-used subnet range in {}".
302 format(self.vnet_address_space))
jamartinezv14a823d2019-08-01 11:45:15 +0200303 else:
304 ip_profile = {"subnet_address": ip_profile['subnet_address']}
305
seryio34478552019-05-23 14:50:49 +0200306 try:
jamartinezv14a823d2019-08-01 11:45:15 +0200307 #subnet_name = "{}-{}".format(net_name[:24], uuid4())
lloretgalleg45220152019-10-29 11:53:49 +0100308 subnet_params = {
tierno24620412019-06-03 14:05:08 +0000309 'address_prefix': ip_profile['subnet_address']
seryio34478552019-05-23 14:50:49 +0200310 }
lloretgalleg45220152019-10-29 11:53:49 +0100311 # Assign a not duplicated net name
312 subnet_name = self._get_unused_subnet_name(net_name)
jamartinezv14a823d2019-08-01 11:45:15 +0200313
lloretgalleg45220152019-10-29 11:53:49 +0100314 self.logger.debug('creating subnet_name: {}'.format(subnet_name))
315 async_creation = self.conn_vnet.subnets.create_or_update(self.resource_group, self.vnet_name,
316 subnet_name, subnet_params)
317 async_creation.wait()
318 self.logger.debug('created subnet_name: {}'.format(subnet_name))
319
jamartinezv14a823d2019-08-01 11:45:15 +0200320 return "{}/subnets/{}".format(self.vnet_id, subnet_name), None
seryio34478552019-05-23 14:50:49 +0200321 except Exception as e:
lloretgalleg45220152019-10-29 11:53:49 +0100322 self._format_vimconn_exception(e)
323
324 def _get_unused_subnet_name(self, subnet_name):
325 """
326 Adds a prefix to the subnet_name with a number in case the indicated name is repeated
327 Checks subnets with the indicated name (without suffix) and adds a suffix with a number
328 """
329 all_subnets = self.conn_vnet.subnets.list(self.resource_group, self.vnet_name)
330 # Filter to subnets starting with the indicated name
331 subnets = list(filter(lambda subnet: (subnet.name.startswith(subnet_name)), all_subnets))
332 net_names = [str(subnet.name) for subnet in subnets]
333
334 # get the name with the first not used suffix
335 name_suffix = 0
336 #name = subnet_name + "-" + str(name_suffix)
337 name = subnet_name # first subnet created will have no prefix
338 while name in net_names:
339 name_suffix += 1
340 name = subnet_name + "-" + str(name_suffix)
341 return name
seryio34478552019-05-23 14:50:49 +0200342
jamartinezv14a823d2019-08-01 11:45:15 +0200343 def _create_nic(self, net, nic_name, static_ip=None):
seryio34478552019-05-23 14:50:49 +0200344
lloretgalleg45220152019-10-29 11:53:49 +0100345 self.logger.debug('create nic name %s, net_name %s', nic_name, net)
jamartinezv14a823d2019-08-01 11:45:15 +0200346 self._reload_connection()
347
348 subnet_id = net['net_id']
349 location = self._get_location_from_resource_group(self.resource_group)
jamartinezv14a823d2019-08-01 11:45:15 +0200350 try:
lloretgallegbfc28b02019-11-21 09:31:16 +0100351 net_ifz = {'location':location}
352 net_ip_config = {'name': nic_name + '-ipconfiguration', 'subnet': {'id': subnet_id}}
jamartinezv14a823d2019-08-01 11:45:15 +0200353 if static_ip:
lloretgallegbfc28b02019-11-21 09:31:16 +0100354 net_ip_config['privateIPAddress'] = static_ip
355 net_ip_config['privateIPAllocationMethod'] = 'Static'
356 net_ifz['ip_configurations'] = [net_ip_config]
357 mac_address = net.get('mac_address')
358 if mac_address:
359 net_ifz['mac_address'] = mac_address
360
361 async_nic_creation = self.conn_vnet.network_interfaces.create_or_update(
jamartinezv14a823d2019-08-01 11:45:15 +0200362 self.resource_group,
363 nic_name,
lloretgallegbfc28b02019-11-21 09:31:16 +0100364 net_ifz
jamartinezv14a823d2019-08-01 11:45:15 +0200365 )
lloretgallegbfc28b02019-11-21 09:31:16 +0100366 async_nic_creation.wait()
lloretgalleg45220152019-10-29 11:53:49 +0100367 self.logger.debug('created nic name %s', nic_name)
jamartinezv14a823d2019-08-01 11:45:15 +0200368
369 public_ip = net.get('floating_ip')
lloretgalleg45220152019-10-29 11:53:49 +0100370 if public_ip:
371 public_ip_address_params = {
jamartinezv14a823d2019-08-01 11:45:15 +0200372 'location': location,
373 'public_ip_allocation_method': 'Dynamic'
374 }
375 public_ip_name = nic_name + '-public-ip'
376 public_ip = self.conn_vnet.public_ip_addresses.create_or_update(
377 self.resource_group,
378 public_ip_name,
lloretgalleg45220152019-10-29 11:53:49 +0100379 public_ip_address_params
jamartinezv14a823d2019-08-01 11:45:15 +0200380 )
lloretgalleg45220152019-10-29 11:53:49 +0100381 self.logger.debug('created public IP: {}'.format(public_ip.result()))
jamartinezv14a823d2019-08-01 11:45:15 +0200382
383 # Asociate NIC to Public IP
jamartinezv14a823d2019-08-01 11:45:15 +0200384 nic_data = self.conn_vnet.network_interfaces.get(
385 self.resource_group,
386 nic_name)
387
388 nic_data.ip_configurations[0].public_ip_address = public_ip.result()
389
jamartinezv14a823d2019-08-01 11:45:15 +0200390 self.conn_vnet.network_interfaces.create_or_update(
391 self.resource_group,
392 nic_name,
393 nic_data)
394
395 except Exception as e:
lloretgalleg45220152019-10-29 11:53:49 +0100396 self._format_vimconn_exception(e)
jamartinezv14a823d2019-08-01 11:45:15 +0200397
seryio34478552019-05-23 14:50:49 +0200398 return async_nic_creation.result()
399
jamartinezv14a823d2019-08-01 11:45:15 +0200400 def new_flavor(self, flavor_data):
lloretgalleg45220152019-10-29 11:53:49 +0100401 """
402 It is not allowed to create new flavors in Azure, must always use an existing one
403 """
404 raise vimconn.vimconnAuthException("It is not possible to create new flavors in AZURE")
tiernodeb74b22019-05-27 10:24:50 +0000405
lloretgalleg45220152019-10-29 11:53:49 +0100406 def new_tenant(self, tenant_name, tenant_description):
407 """
408 It is not allowed to create new tenants in azure
409 """
jamartinezv14a823d2019-08-01 11:45:15 +0200410 raise vimconn.vimconnAuthException("It is not possible to create a TENANT in AZURE")
411
412 def new_image(self, image_dict):
lloretgalleg45220152019-10-29 11:53:49 +0100413 """
414 It is not allowed to create new images in Azure, must always use an existing one
415 """
416 raise vimconn.vimconnAuthException("It is not possible to create new images in AZURE")
jamartinezv14a823d2019-08-01 11:45:15 +0200417
418 def get_image_id_from_path(self, path):
419 """Get the image id from image path in the VIM database.
420 Returns the image_id or raises a vimconnNotFoundException
421 """
lloretgalleg45220152019-10-29 11:53:49 +0100422 raise vimconn.vimconnAuthException("It is not possible to obtain image from path in AZURE")
jamartinezv14a823d2019-08-01 11:45:15 +0200423
424 def get_image_list(self, filter_dict={}):
425 """Obtain tenant images from VIM
426 Filter_dict can be:
lloretgalleg45220152019-10-29 11:53:49 +0100427 name: image name with the format: publisher:offer:sku:version
428 If some part of the name is provide ex: publisher:offer it will search all availables skus and version
429 for the provided publisher and offer
430 id: image uuid, currently not supported for azure
jamartinezv14a823d2019-08-01 11:45:15 +0200431 Returns the image list of dictionaries:
432 [{<the fields at Filter_dict plus some VIM specific>}, ...]
433 List can be empty
434 """
lloretgalleg45220152019-10-29 11:53:49 +0100435
436 self.logger.debug("get_image_list filter {}".format(filter_dict))
437
jamartinezv14a823d2019-08-01 11:45:15 +0200438 self._reload_connection()
lloretgalleg45220152019-10-29 11:53:49 +0100439 try:
440 image_list = []
441 if filter_dict.get("name"):
442 # name will have the format 'publisher:offer:sku:version'
443 # publisher is required, offer sku and version will be searched if not provided
444 params = filter_dict["name"].split(":")
tiernodeb74b22019-05-27 10:24:50 +0000445 publisher = params[0]
lloretgalleg45220152019-10-29 11:53:49 +0100446 if publisher:
447 # obtain offer list
448 offer_list = self._get_offer_list(params, publisher)
449 for offer in offer_list:
450 # obtain skus
451 sku_list = self._get_sku_list(params, publisher, offer)
452 for sku in sku_list:
453 # if version is defined get directly version, else list images
454 if len(params) == 4 and params[3]:
455 version = params[3]
456 image_list = self._get_version_image_list(publisher, offer, sku, version)
457 else:
458 image_list = self._get_sku_image_list(publisher, offer, sku)
459 else:
460 raise vimconn.vimconnAuthException(
461 "List images in Azure must include name param with at least publisher")
462 else:
463 raise vimconn.vimconnAuthException("List images in Azure must include name param with at"
464 " least publisher")
tiernodeb74b22019-05-27 10:24:50 +0000465
lloretgalleg45220152019-10-29 11:53:49 +0100466 return image_list
467 except Exception as e:
468 self._format_vimconn_exception(e)
469
470 def _get_offer_list(self, params, publisher):
471 """
472 Helper method to obtain offer list for defined publisher
473 """
474 if len(params) >= 2 and params[1]:
475 return [params[1]]
476 else:
477 try:
478 # get list of offers from azure
479 result_offers = self.conn_compute.virtual_machine_images.list_offers(self.region, publisher)
480 return [offer.name for offer in result_offers]
481 except CloudError as e:
482 # azure raises CloudError when not found
483 self.logger.info("error listing offers for publisher {}, message: {}".format(publisher, e.message))
484 return []
485
486 def _get_sku_list(self, params, publisher, offer):
487 """
488 Helper method to obtain sku list for defined publisher and offer
489 """
490 if len(params) >= 3 and params[2]:
491 return [params[2]]
492 else:
493 try:
494 # get list of skus from azure
495 result_skus = self.conn_compute.virtual_machine_images.list_skus(self.region, publisher, offer)
496 return [sku.name for sku in result_skus]
497 except CloudError as e:
498 # azure raises CloudError when not found
499 self.logger.info("error listing skus for publisher {}, offer {}, message: {}".format(publisher, offer, e.message))
500 return []
501
502 def _get_sku_image_list(self, publisher, offer, sku):
503 """
504 Helper method to obtain image list for publisher, offer and sku
505 """
506 image_list = []
507 try:
508 result_images = self.conn_compute.virtual_machine_images.list(self.region, publisher, offer, sku)
509 for result_image in result_images:
510 image_list.append({
511 'id': str(result_image.id),
512 'name': ":".join([publisher, offer, sku, result_image.name])
513 })
514 except CloudError as e:
515 self.logger.info(
516 "error listing skus for publisher {}, offer {}, message: {}".format(publisher, offer, e.message))
517 image_list = []
518 return image_list
519
520 def _get_version_image_list(self, publisher, offer, sku, version):
521 image_list = []
522 try:
523 result_image = self.conn_compute.virtual_machine_images.get(self.region, publisher, offer, sku, version)
524 if result_image:
525 image_list.append({
526 'id': str(result_image.id),
527 'name': ":".join([publisher, offer, sku, version])
528 })
529 except CloudError as e:
530 # azure gives CloudError when not found
531 self.logger.info(
532 "error listing images for publisher {}, offer {}, sku {}, vesion {} message: {}".format(publisher,
533 offer,
534 sku,
535 version,
536 e.message))
537 image_list = []
tiernodeb74b22019-05-27 10:24:50 +0000538 return image_list
539
seryio34478552019-05-23 14:50:49 +0200540 def get_network_list(self, filter_dict={}):
tiernodeb74b22019-05-27 10:24:50 +0000541 """Obtain tenant networks of VIM
seryio34478552019-05-23 14:50:49 +0200542 Filter_dict can be:
543 name: network name
lloretgalleg45220152019-10-29 11:53:49 +0100544 id: network id
545 shared: boolean, not implemented in Azure
546 tenant_id: tenant, not used in Azure, all networks same tenants
547 admin_state_up: boolean, not implemented in Azure
548 status: 'ACTIVE', not implemented in Azure #
seryio34478552019-05-23 14:50:49 +0200549 Returns the network list of dictionaries
tiernodeb74b22019-05-27 10:24:50 +0000550 """
lloretgalleg45220152019-10-29 11:53:49 +0100551 #self.logger.debug('getting network list for vim, filter %s', filter_dict)
seryio34478552019-05-23 14:50:49 +0200552 try:
553 self._reload_connection()
jamartinezv14a823d2019-08-01 11:45:15 +0200554
555 vnet = self.conn_vnet.virtual_networks.get(self.resource_group, self.vnet_name)
seryio34478552019-05-23 14:50:49 +0200556 subnet_list = []
jamartinezv14a823d2019-08-01 11:45:15 +0200557
seryio34478552019-05-23 14:50:49 +0200558 for subnet in vnet.subnets:
seryio34478552019-05-23 14:50:49 +0200559 if filter_dict:
560 if filter_dict.get("id") and str(subnet.id) != filter_dict["id"]:
561 continue
562 if filter_dict.get("name") and \
lloretgalleg45220152019-10-29 11:53:49 +0100563 str(subnet.name) != filter_dict["name"]:
seryio34478552019-05-23 14:50:49 +0200564 continue
565
jamartinezv14a823d2019-08-01 11:45:15 +0200566 name = self._get_resource_name_from_resource_id(subnet.id)
567
seryio34478552019-05-23 14:50:49 +0200568 subnet_list.append({
569 'id': str(subnet.id),
jamartinezv14a823d2019-08-01 11:45:15 +0200570 'name': self._get_resource_name_from_resource_id(subnet.id),
lloretgalleg45220152019-10-29 11:53:49 +0100571 'status': self.provision_state2osm[subnet.provisioning_state],
jamartinezv14a823d2019-08-01 11:45:15 +0200572 'cidr_block': str(subnet.address_prefix),
573 'type': 'bridge',
574 'shared': False
seryio34478552019-05-23 14:50:49 +0200575 }
576 )
jamartinezv14a823d2019-08-01 11:45:15 +0200577
seryio34478552019-05-23 14:50:49 +0200578 return subnet_list
579 except Exception as e:
lloretgalleg45220152019-10-29 11:53:49 +0100580 self._format_vimconn_exception(e)
seryio34478552019-05-23 14:50:49 +0200581
582 def new_vminstance(self, vm_name, description, start, image_id, flavor_id, net_list, cloud_config=None,
583 disk_list=None, availability_zone_index=None, availability_zone_list=None):
584
585 return self._new_vminstance(vm_name, image_id, flavor_id, net_list)
lloretgalleg45220152019-10-29 11:53:49 +0100586
jamartinezv14a823d2019-08-01 11:45:15 +0200587 def new_vminstance(self, name, description, start, image_id, flavor_id, net_list, cloud_config=None,
lloretgalleg45220152019-10-29 11:53:49 +0100588 disk_list=None, availability_zone_index=None, availability_zone_list=None):
589
590 self.logger.debug("new vm instance name: %s, image_id: %s, flavor_id: %s, net_list: %s, cloud_config: %s"
591 + "disk_list: %s, availability_zone_index: %s, availability_zone_list: %s",
592 name, image_id, flavor_id, net_list, cloud_config, disk_list,
593 availability_zone_index, availability_zone_list)
594
595 self._reload_connection()
596
597 # Validate input data is valid
598 # The virtual machine name must have less or 64 characters and it can not have the following
599 # characters: (~ ! @ # $ % ^ & * ( ) = + _ [ ] { } \ | ; : ' " , < > / ?.)
600 vm_name = self._check_vm_name(name)
601 # Obtain vm unused name
602 vm_name = self._get_unused_vm_name(vm_name)
603
604 # At least one network must be provided
605 if not net_list:
606 raise vimconn.vimconnException("At least one net must be provided to create a new VM")
607
608 # image_id are several fields of the image_id
609 image_reference = self._get_image_reference(image_id)
jamartinezv14a823d2019-08-01 11:45:15 +0200610
seryio34478552019-05-23 14:50:49 +0200611 self._check_subnets_for_vm(net_list)
612 vm_nics = []
613 for idx, net in enumerate(net_list):
jamartinezv14a823d2019-08-01 11:45:15 +0200614 # Fault with subnet_id
615 # subnet_id=net['subnet_id']
616 # subnet_id=net['net_id']
lloretgalleg45220152019-10-29 11:53:49 +0100617 nic_name = vm_name + '-nic-'+str(idx)
lloretgallegbfc28b02019-11-21 09:31:16 +0100618 vm_nic = self._create_nic(net, nic_name, net.get('ip_address'))
lloretgalleg45220152019-10-29 11:53:49 +0100619 vm_nics.append({'id': str(vm_nic.id)})
620 net['vim_id'] = vm_nic.id
seryio34478552019-05-23 14:50:49 +0200621
622 try:
jamartinezv14a823d2019-08-01 11:45:15 +0200623
624 # cloud-init configuration
625 # cloud config
626 if cloud_config:
627 config_drive, userdata = self._create_user_data(cloud_config)
628 custom_data = base64.b64encode(userdata.encode('utf-8')).decode('latin-1')
lloretgalleg45220152019-10-29 11:53:49 +0100629 key_data = None
630 key_pairs = cloud_config.get("key-pairs")
631 if key_pairs:
632 key_data = key_pairs[0]
633
634 if cloud_config.get("users"):
635 user_name = cloud_config.get("users")[0].get("name", "osm")
636 else:
637 user_name = "osm" # DEFAULT USER IS OSM
638
jamartinezv14a823d2019-08-01 11:45:15 +0200639 os_profile = {
lloretgalleg45220152019-10-29 11:53:49 +0100640 'computer_name': vm_name,
641 'admin_username': user_name,
642 'linux_configuration': {
643 "disable_password_authentication": True,
644 "ssh": {
645 "public_keys": [{
646 "path": "/home/{}/.ssh/authorized_keys".format(user_name),
647 "key_data": key_data
648 }]
649 }
650 },
jamartinezv14a823d2019-08-01 11:45:15 +0200651 'custom_data': custom_data
652 }
653 else:
654 os_profile = {
lloretgalleg45220152019-10-29 11:53:49 +0100655 'computer_name': vm_name
656 ,'admin_username': 'osm'
657 ,'admin_password': 'Osm4u!',
jamartinezv14a823d2019-08-01 11:45:15 +0200658 }
659
seryio34478552019-05-23 14:50:49 +0200660 vm_parameters = {
661 'location': self.region,
jamartinezv14a823d2019-08-01 11:45:15 +0200662 'os_profile': os_profile,
seryio34478552019-05-23 14:50:49 +0200663 'hardware_profile': {
jamartinezv14a823d2019-08-01 11:45:15 +0200664 'vm_size': flavor_id
seryio34478552019-05-23 14:50:49 +0200665 },
666 'storage_profile': {
jamartinezv14a823d2019-08-01 11:45:15 +0200667 'image_reference': image_reference
seryio34478552019-05-23 14:50:49 +0200668 }
669 }
jamartinezv14a823d2019-08-01 11:45:15 +0200670
lloretgalleg45220152019-10-29 11:53:49 +0100671 # Add data disks if they are provided
672 if disk_list:
673 data_disks = []
674 for lun_name, disk in enumerate(disk_list):
675 self.logger.debug("add disk size: %s, image: %s", disk.get("size"), disk.get("image_id"))
676 if not disk.get("image_id"):
677 data_disks.append({
678 'lun': lun_name, # You choose the value, depending of what is available for you
679 'name': vm_name + "_data_disk-" + str(lun_name),
lloretgallegbfc28b02019-11-21 09:31:16 +0100680 'create_option': DiskCreateOption.empty,
lloretgalleg45220152019-10-29 11:53:49 +0100681 'disk_size_gb': disk.get("size")
682 })
683 else:
lloretgallegbfc28b02019-11-21 09:31:16 +0100684 #self.logger.debug("currently not able to create data disks from image for azure, ignoring")
685 data_disks.append({
686 'lun': lun_name, # You choose the value, depending of what is available for you
687 'name': vm_name + "_data_disk-" + str(lun_name),
688 'create_option': 'Attach',
689 'disk_size_gb': disk.get("size"),
690 'managed_disk': {
691 'id': disk.get("image_id")
692 }
693 })
lloretgalleg45220152019-10-29 11:53:49 +0100694
695 if data_disks:
696 vm_parameters["storage_profile"]["data_disks"] = data_disks
697
698 # If the machine has several networks one must be marked as primary
699 # As it is not indicated in the interface the first interface will be marked as primary
700 if len(vm_nics) > 1:
701 for idx, vm_nic in enumerate(vm_nics):
702 if idx == 0:
703 vm_nics[0]['Primary'] = True
704 else:
705 vm_nics[idx]['Primary'] = False
706
707 vm_parameters['network_profile'] = {'network_interfaces': vm_nics}
708
709 self.logger.debug("create vm name: %s", vm_name)
seryio34478552019-05-23 14:50:49 +0200710 creation_result = self.conn_compute.virtual_machines.create_or_update(
711 self.resource_group,
lloretgalleg45220152019-10-29 11:53:49 +0100712 vm_name,
seryio34478552019-05-23 14:50:49 +0200713 vm_parameters
714 )
jamartinezv14a823d2019-08-01 11:45:15 +0200715 #creation_result.wait()
716 result = creation_result.result()
lloretgallegbfc28b02019-11-21 09:31:16 +0100717 self.logger.debug("created vm name: %s", vm_name)
jamartinezv14a823d2019-08-01 11:45:15 +0200718
lloretgalleg45220152019-10-29 11:53:49 +0100719 if start:
jamartinezv14a823d2019-08-01 11:45:15 +0200720 start_result = self.conn_compute.virtual_machines.start(
721 self.resource_group,
lloretgalleg45220152019-10-29 11:53:49 +0100722 vm_name)
jamartinezv14a823d2019-08-01 11:45:15 +0200723 #start_result.wait()
724
725 return result.id, None
726
727 #run_command_parameters = {
728 # 'command_id': 'RunShellScript', # For linux, don't change it
729 # 'script': [
730 # 'date > /tmp/test.txt'
731 # ]
732 #}
seryio34478552019-05-23 14:50:49 +0200733 except Exception as e:
lloretgalleg45220152019-10-29 11:53:49 +0100734 self.logger.debug('Exception creating new vminstance: %s', e, exc_info=True)
735 self._format_vimconn_exception(e)
736
737 def _get_unused_vm_name(self, vm_name):
738 """
739 Checks the vm name and in case it is used adds a suffix to the name to allow creation
740 :return:
741 """
742 all_vms = self.conn_compute.virtual_machines.list(self.resource_group)
743 # Filter to vms starting with the indicated name
744 vms = list(filter(lambda vm: (vm.name.startswith(vm_name)), all_vms))
745 vm_names = [str(vm.name) for vm in vms]
746
747 # get the name with the first not used suffix
748 name_suffix = 0
749 # name = subnet_name + "-" + str(name_suffix)
750 name = vm_name # first subnet created will have no prefix
751 while name in vm_names:
752 name_suffix += 1
753 name = vm_name + "-" + str(name_suffix)
754 return name
755
seryio34478552019-05-23 14:50:49 +0200756
jamartinezv14a823d2019-08-01 11:45:15 +0200757 # It is necesary extract from image_id data to create the VM with this format
758 # 'image_reference': {
759 # 'publisher': vm_reference['publisher'],
760 # 'offer': vm_reference['offer'],
761 # 'sku': vm_reference['sku'],
762 # 'version': vm_reference['version']
763 # },
lloretgalleg45220152019-10-29 11:53:49 +0100764 def _get_image_reference(self, image_id):
jamartinezv14a823d2019-08-01 11:45:15 +0200765
lloretgalleg45220152019-10-29 11:53:49 +0100766 try:
767 # The data input format example:
768 # /Subscriptions/ca3d18ab-d373-4afb-a5d6-7c44f098d16a/Providers/Microsoft.Compute/Locations/westeurope/
769 # Publishers/Canonical/ArtifactTypes/VMImage/
770 # Offers/UbuntuServer/
771 # Skus/18.04-LTS/
772 # Versions/18.04.201809110
773 publisher = str(image_id.split('/')[8])
774 offer = str(image_id.split('/')[12])
775 sku = str(image_id.split('/')[14])
776 version = str(image_id.split('/')[16])
jamartinezv14a823d2019-08-01 11:45:15 +0200777
lloretgalleg45220152019-10-29 11:53:49 +0100778 return {
779 'publisher': publisher,
780 'offer': offer,
781 'sku': sku,
782 'version': version
783 }
784 except Exception as e:
785 raise vimconn.vimconnException(
786 "Unable to get image_reference from invalid image_id format: '{}'".format(image_id))
jamartinezv14a823d2019-08-01 11:45:15 +0200787
788 # Azure VM names can not have some special characters
lloretgalleg45220152019-10-29 11:53:49 +0100789 def _check_vm_name(self, vm_name):
790 """
791 Checks vm name, in case the vm has not allowed characters they are removed, not error raised
792 """
jamartinezv14a823d2019-08-01 11:45:15 +0200793
794 #chars_not_allowed_list = ['~','!','@','#','$','%','^','&','*','(',')','=','+','_','[',']','{','}','|',';',':','<','>','/','?','.']
795 chars_not_allowed_list = "~!@#$%^&*()=+_[]{}|;:<>/?."
796
797 # First: the VM name max length is 64 characters
798 vm_name_aux = vm_name[:64]
799
800 # Second: replace not allowed characters
lloretgalleg45220152019-10-29 11:53:49 +0100801 for elem in chars_not_allowed_list:
jamartinezv14a823d2019-08-01 11:45:15 +0200802 # Check if string is in the main string
lloretgalleg45220152019-10-29 11:53:49 +0100803 if elem in vm_name_aux:
jamartinezv14a823d2019-08-01 11:45:15 +0200804 #self.logger.debug('Dentro del IF')
805 # Replace the string
806 vm_name_aux = vm_name_aux.replace(elem, '-')
807
808 return vm_name_aux
809
seryio34478552019-05-23 14:50:49 +0200810 def get_flavor_id_from_data(self, flavor_dict):
seryio34478552019-05-23 14:50:49 +0200811
lloretgalleg45220152019-10-29 11:53:49 +0100812 self.logger.debug("getting flavor id from data, flavor_dict: %s", flavor_dict)
813 filter_dict = flavor_dict or {}
jamartinezv14a823d2019-08-01 11:45:15 +0200814 try:
815 self._reload_connection()
816 vm_sizes_list = [vm_size.serialize() for vm_size in self.conn_compute.virtual_machine_sizes.list(self.region)]
tierno30d0d6d2019-05-27 08:14:01 +0000817
lloretgalleg45220152019-10-29 11:53:49 +0100818 cpus = filter_dict.get('vcpus') or 0
819 memMB = filter_dict.get('ram') or 0
tierno30d0d6d2019-05-27 08:14:01 +0000820
lloretgalleg45220152019-10-29 11:53:49 +0100821 # Filter
822 if self._config.get("flavors_pattern"):
823 filtered_sizes = [size for size in vm_sizes_list if size['numberOfCores'] >= cpus
824 and size['memoryInMB'] >= memMB
825 and re.search(self._config.get("flavors_pattern"), size["name"])]
826 else:
827 filtered_sizes = [size for size in vm_sizes_list if size['numberOfCores'] >= cpus
828 and size['memoryInMB'] >= memMB]
jamartinezv14a823d2019-08-01 11:45:15 +0200829
lloretgalleg45220152019-10-29 11:53:49 +0100830
831
832 # Sort
833 listedFilteredSizes = sorted(filtered_sizes, key=lambda k: (k['numberOfCores'], k['memoryInMB'], k['resourceDiskSizeInMB']))
834
835 if listedFilteredSizes:
836 return listedFilteredSizes[0]['name']
837 raise vimconn.vimconnNotFoundException("Cannot find any flavor matching '{}'".format(str(flavor_dict)))
jamartinezv14a823d2019-08-01 11:45:15 +0200838
839 except Exception as e:
lloretgalleg45220152019-10-29 11:53:49 +0100840 self._format_vimconn_exception(e)
jamartinezv14a823d2019-08-01 11:45:15 +0200841
842 def _get_flavor_id_from_flavor_name(self, flavor_name):
jamartinezv14a823d2019-08-01 11:45:15 +0200843
lloretgalleg45220152019-10-29 11:53:49 +0100844 #self.logger.debug("getting flavor id from flavor name {}".format(flavor_name))
jamartinezv14a823d2019-08-01 11:45:15 +0200845 try:
846 self._reload_connection()
847 vm_sizes_list = [vm_size.serialize() for vm_size in self.conn_compute.virtual_machine_sizes.list(self.region)]
848
849 output_flavor = None
850 for size in vm_sizes_list:
851 if size['name'] == flavor_name:
852 output_flavor = size
853
lloretgalleg45220152019-10-29 11:53:49 +0100854 # Si no se encuentra ninguno, este metodo devuelve None
jamartinezv14a823d2019-08-01 11:45:15 +0200855 return output_flavor
856
857 except Exception as e:
lloretgalleg45220152019-10-29 11:53:49 +0100858 self._format_vimconn_exception(e)
tierno30d0d6d2019-05-27 08:14:01 +0000859
860 def check_vim_connectivity(self):
seryio34478552019-05-23 14:50:49 +0200861 try:
862 self._reload_connection()
tierno30d0d6d2019-05-27 08:14:01 +0000863 return True
864 except Exception as e:
865 raise vimconn.vimconnException("Connectivity issue with Azure API: {}".format(e))
seryio34478552019-05-23 14:50:49 +0200866
867 def get_network(self, net_id):
seryio34478552019-05-23 14:50:49 +0200868
lloretgalleg45220152019-10-29 11:53:49 +0100869 #self.logger.debug('get network id: {}'.format(net_id))
870 res_name = self._get_resource_name_from_resource_id(net_id)
seryio34478552019-05-23 14:50:49 +0200871 self._reload_connection()
jamartinezv14a823d2019-08-01 11:45:15 +0200872
lloretgalleg45220152019-10-29 11:53:49 +0100873 filter_dict = {'name': net_id}
jamartinezv14a823d2019-08-01 11:45:15 +0200874 network_list = self.get_network_list(filter_dict)
875
876 if not network_list:
877 raise vimconn.vimconnNotFoundException("network '{}' not found".format(net_id))
878 else:
879 return network_list[0]
880
jamartinezv14a823d2019-08-01 11:45:15 +0200881 def delete_network(self, net_id, created_items=None):
882
lloretgalleg45220152019-10-29 11:53:49 +0100883 self.logger.debug('deleting network {} - {}'.format(self.resource_group, net_id))
jamartinezv14a823d2019-08-01 11:45:15 +0200884
885 self._reload_connection()
lloretgalleg45220152019-10-29 11:53:49 +0100886 res_name = self._get_resource_name_from_resource_id(net_id)
887 filter_dict = {'name': res_name}
jamartinezv14a823d2019-08-01 11:45:15 +0200888 network_list = self.get_network_list(filter_dict)
889 if not network_list:
890 raise vimconn.vimconnNotFoundException("network '{}' not found".format(net_id))
891
892 try:
893 # Subnet API fails (CloudError: Azure Error: ResourceNotFound)
894 # Put the initial virtual_network API
lloretgalleg45220152019-10-29 11:53:49 +0100895 async_delete = self.conn_vnet.subnets.delete(self.resource_group, self.vnet_name, res_name)
896 async_delete.wait()
jamartinezv14a823d2019-08-01 11:45:15 +0200897 return net_id
898
899 except CloudError as e:
lloretgalleg45220152019-10-29 11:53:49 +0100900 if e.error.error and "notfound" in e.error.error.lower():
jamartinezv14a823d2019-08-01 11:45:15 +0200901 raise vimconn.vimconnNotFoundException("network '{}' not found".format(net_id))
902 else:
lloretgalleg45220152019-10-29 11:53:49 +0100903 self._format_vimconn_exception(e)
jamartinezv14a823d2019-08-01 11:45:15 +0200904 except Exception as e:
lloretgalleg45220152019-10-29 11:53:49 +0100905 self._format_vimconn_exception(e)
jamartinezv14a823d2019-08-01 11:45:15 +0200906
jamartinezv14a823d2019-08-01 11:45:15 +0200907 def delete_vminstance(self, vm_id, created_items=None):
lloretgalleg45220152019-10-29 11:53:49 +0100908 """ Deletes a vm instance from the vim.
909 """
910 self.logger.debug('deleting VM instance {} - {}'.format(self.resource_group, vm_id))
jamartinezv14a823d2019-08-01 11:45:15 +0200911 self._reload_connection()
912
913 try:
914
lloretgalleg45220152019-10-29 11:53:49 +0100915 res_name = self._get_resource_name_from_resource_id(vm_id)
916 vm = self.conn_compute.virtual_machines.get(self.resource_group, res_name)
jamartinezv14a823d2019-08-01 11:45:15 +0200917
918 # Shuts down the virtual machine and releases the compute resources
919 #vm_stop = self.conn_compute.virtual_machines.power_off(self.resource_group, resName)
920 #vm_stop.wait()
921
lloretgalleg45220152019-10-29 11:53:49 +0100922 vm_delete = self.conn_compute.virtual_machines.delete(self.resource_group, res_name)
jamartinezv14a823d2019-08-01 11:45:15 +0200923 vm_delete.wait()
lloretgalleg45220152019-10-29 11:53:49 +0100924 self.logger.debug('deleted VM name: %s', res_name)
jamartinezv14a823d2019-08-01 11:45:15 +0200925
926 # Delete OS Disk
927 os_disk_name = vm.storage_profile.os_disk.name
lloretgalleg45220152019-10-29 11:53:49 +0100928 self.logger.debug('delete OS DISK: %s', os_disk_name)
jamartinezv14a823d2019-08-01 11:45:15 +0200929 self.conn_compute.disks.delete(self.resource_group, os_disk_name)
lloretgalleg45220152019-10-29 11:53:49 +0100930 self.logger.debug('deleted OS DISK name: %s', os_disk_name)
jamartinezv14a823d2019-08-01 11:45:15 +0200931
lloretgalleg45220152019-10-29 11:53:49 +0100932 for data_disk in vm.storage_profile.data_disks:
933 self.logger.debug('delete data_disk: %s', data_disk.name)
934 self.conn_compute.disks.delete(self.resource_group, data_disk.name)
935 self.logger.debug('deleted OS DISK name: %s', data_disk.name)
936
937 # After deleting VM, it is necessary to delete NIC, because if is not deleted delete_network
jamartinezv14a823d2019-08-01 11:45:15 +0200938 # does not work because Azure says that is in use the subnet
939 network_interfaces = vm.network_profile.network_interfaces
940
941 for network_interface in network_interfaces:
942
jamartinezv14a823d2019-08-01 11:45:15 +0200943 nic_name = self._get_resource_name_from_resource_id(network_interface.id)
jamartinezv14a823d2019-08-01 11:45:15 +0200944 nic_data = self.conn_vnet.network_interfaces.get(
945 self.resource_group,
946 nic_name)
947
lloretgalleg45220152019-10-29 11:53:49 +0100948 public_ip_name = None
jamartinezv14a823d2019-08-01 11:45:15 +0200949 exist_public_ip = nic_data.ip_configurations[0].public_ip_address
950 if exist_public_ip:
951 public_ip_id = nic_data.ip_configurations[0].public_ip_address.id
jamartinezv14a823d2019-08-01 11:45:15 +0200952
953 # Delete public_ip
954 public_ip_name = self._get_resource_name_from_resource_id(public_ip_id)
955
lloretgalleg45220152019-10-29 11:53:49 +0100956 # Public ip must be deleted afterwards of nic that is attached
jamartinezv14a823d2019-08-01 11:45:15 +0200957
lloretgalleg45220152019-10-29 11:53:49 +0100958 self.logger.debug('delete NIC name: %s', nic_name)
959 nic_delete = self.conn_vnet.network_interfaces.delete(self.resource_group, nic_name)
960 nic_delete.wait()
961 self.logger.debug('deleted NIC name: %s', nic_name)
962
963 # Delete list of public ips
964 if public_ip_name:
965 self.logger.debug('delete PUBLIC IP - ' + public_ip_name)
966 public_ip = self.conn_vnet.public_ip_addresses.delete(self.resource_group, public_ip_name)
967
968 except CloudError as e:
969 if e.error.error and "notfound" in e.error.error.lower():
970 raise vimconn.vimconnNotFoundException("No vm instance found '{}'".format(vm_id))
971 else:
972 self._format_vimconn_exception(e)
973 except Exception as e:
974 self._format_vimconn_exception(e)
975
976 def action_vminstance(self, vm_id, action_dict, created_items = {}):
jamartinezv14a823d2019-08-01 11:45:15 +0200977 """Send and action over a VM instance from VIM
lloretgalleg45220152019-10-29 11:53:49 +0100978 Returns the vm_id if the action was successfully sent to the VIM
979 """
jamartinezv14a823d2019-08-01 11:45:15 +0200980
981 self.logger.debug("Action over VM '%s': %s", vm_id, str(action_dict))
982 try:
983 self._reload_connection()
984 resName = self._get_resource_name_from_resource_id(vm_id)
985 if "start" in action_dict:
lloretgalleg45220152019-10-29 11:53:49 +0100986 self.conn_compute.virtual_machines.start(self.resource_group, resName)
jamartinezv14a823d2019-08-01 11:45:15 +0200987 elif "stop" in action_dict or "shutdown" in action_dict or "shutoff" in action_dict:
lloretgalleg45220152019-10-29 11:53:49 +0100988 self.conn_compute.virtual_machines.power_off(self.resource_group, resName)
jamartinezv14a823d2019-08-01 11:45:15 +0200989 elif "terminate" in action_dict:
lloretgalleg45220152019-10-29 11:53:49 +0100990 self.conn_compute.virtual_machines.delete(self.resource_group, resName)
jamartinezv14a823d2019-08-01 11:45:15 +0200991 elif "reboot" in action_dict:
lloretgalleg45220152019-10-29 11:53:49 +0100992 self.conn_compute.virtual_machines.restart(self.resource_group, resName)
jamartinezv14a823d2019-08-01 11:45:15 +0200993 return None
994 except CloudError as e:
lloretgalleg45220152019-10-29 11:53:49 +0100995 if e.error.error and "notfound" in e.error.error.lower():
jamartinezv14a823d2019-08-01 11:45:15 +0200996 raise vimconn.vimconnNotFoundException("No vm found '{}'".format(vm_id))
997 else:
lloretgalleg45220152019-10-29 11:53:49 +0100998 self._format_vimconn_exception(e)
jamartinezv14a823d2019-08-01 11:45:15 +0200999 except Exception as e:
lloretgalleg45220152019-10-29 11:53:49 +01001000 self._format_vimconn_exception(e)
jamartinezv14a823d2019-08-01 11:45:15 +02001001
1002 def delete_flavor(self, flavor_id):
jamartinezv14a823d2019-08-01 11:45:15 +02001003 raise vimconn.vimconnAuthException("It is not possible to delete a FLAVOR in AZURE")
1004
lloretgalleg45220152019-10-29 11:53:49 +01001005 def delete_tenant(self, tenant_id,):
jamartinezv14a823d2019-08-01 11:45:15 +02001006 raise vimconn.vimconnAuthException("It is not possible to delete a TENANT in AZURE")
1007
1008 def delete_image(self, image_id):
jamartinezv14a823d2019-08-01 11:45:15 +02001009 raise vimconn.vimconnAuthException("It is not possible to delete a IMAGE in AZURE")
seryio34478552019-05-23 14:50:49 +02001010
1011 def get_vminstance(self, vm_id):
lloretgalleg45220152019-10-29 11:53:49 +01001012 """
1013 Obtaing the vm instance data from v_id
1014 """
1015 self.logger.debug("get vm instance: %s", vm_id)
seryio34478552019-05-23 14:50:49 +02001016 self._reload_connection()
jamartinezv14a823d2019-08-01 11:45:15 +02001017 try:
1018 resName = self._get_resource_name_from_resource_id(vm_id)
1019 vm=self.conn_compute.virtual_machines.get(self.resource_group, resName)
1020 except CloudError as e:
lloretgalleg45220152019-10-29 11:53:49 +01001021 if e.error.error and "notfound" in e.error.error.lower():
jamartinezv14a823d2019-08-01 11:45:15 +02001022 raise vimconn.vimconnNotFoundException("No vminstance found '{}'".format(vm_id))
1023 else:
lloretgalleg45220152019-10-29 11:53:49 +01001024 self._format_vimconn_exception(e)
jamartinezv14a823d2019-08-01 11:45:15 +02001025 except Exception as e:
lloretgalleg45220152019-10-29 11:53:49 +01001026 self._format_vimconn_exception(e)
seryio34478552019-05-23 14:50:49 +02001027
1028 return vm
1029
1030 def get_flavor(self, flavor_id):
lloretgalleg45220152019-10-29 11:53:49 +01001031 """
1032 Obtains the flavor_data from the flavor_id
1033 """
seryio34478552019-05-23 14:50:49 +02001034 self._reload_connection()
lloretgalleg45220152019-10-29 11:53:49 +01001035 self.logger.debug("get flavor from id: %s", flavor_id)
jamartinezv14a823d2019-08-01 11:45:15 +02001036 flavor_data = self._get_flavor_id_from_flavor_name(flavor_id)
1037 if flavor_data:
1038 flavor = {
1039 'id': flavor_id,
1040 'name': flavor_id,
1041 'ram': flavor_data['memoryInMB'],
1042 'vcpus': flavor_data['numberOfCores'],
lloretgalleg45220152019-10-29 11:53:49 +01001043 'disk': flavor_data['resourceDiskSizeInMB']/1024
jamartinezv14a823d2019-08-01 11:45:15 +02001044 }
1045 return flavor
1046 else:
1047 raise vimconn.vimconnNotFoundException("flavor '{}' not found".format(flavor_id))
1048
jamartinezv14a823d2019-08-01 11:45:15 +02001049 def get_tenant_list(self, filter_dict={}):
lloretgalleg45220152019-10-29 11:53:49 +01001050 """ Obtains the list of tenants
1051 For the azure connector only the azure tenant will be returned if it is compatible
1052 with filter_dict
1053 """
jamartinezv14a823d2019-08-01 11:45:15 +02001054 tenants_azure=[{'name': self.tenant, 'id': self.tenant}]
1055 tenant_list=[]
1056
lloretgalleg45220152019-10-29 11:53:49 +01001057 self.logger.debug("get tenant list: %s", filter_dict)
jamartinezv14a823d2019-08-01 11:45:15 +02001058 for tenant_azure in tenants_azure:
1059 if filter_dict:
1060 if filter_dict.get("id") and str(tenant_azure.get("id")) != filter_dict["id"]:
1061 continue
lloretgalleg45220152019-10-29 11:53:49 +01001062 if filter_dict.get("name") and str(tenant_azure.get("name")) != filter_dict["name"]:
jamartinezv14a823d2019-08-01 11:45:15 +02001063 continue
1064
1065 tenant_list.append(tenant_azure)
1066
1067 return tenant_list
seryio34478552019-05-23 14:50:49 +02001068
tierno84efdc12019-05-29 09:29:01 +00001069 def refresh_nets_status(self, net_list):
lloretgalleg45220152019-10-29 11:53:49 +01001070 """Get the status of the networks
1071 Params: the list of network identifiers
1072 Returns a dictionary with:
1073 net_id: #VIM id of this network
1074 status: #Mandatory. Text with one of:
1075 # DELETED (not found at vim)
1076 # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
1077 # OTHER (Vim reported other status not understood)
1078 # ERROR (VIM indicates an ERROR status)
1079 # ACTIVE, INACTIVE, DOWN (admin down),
1080 # BUILD (on building process)
1081 #
1082 error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
1083 vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
1084
1085 """
jamartinezv14a823d2019-08-01 11:45:15 +02001086
tierno84efdc12019-05-29 09:29:01 +00001087 out_nets = {}
1088 self._reload_connection()
lloretgalleg45220152019-10-29 11:53:49 +01001089
1090 self.logger.debug("reload nets status net_list: %s", net_list)
tierno84efdc12019-05-29 09:29:01 +00001091 for net_id in net_list:
1092 try:
jamartinezv14a823d2019-08-01 11:45:15 +02001093 netName = self._get_net_name_from_resource_id(net_id)
tierno84efdc12019-05-29 09:29:01 +00001094 resName = self._get_resource_name_from_resource_id(net_id)
seryio34478552019-05-23 14:50:49 +02001095
jamartinezv14a823d2019-08-01 11:45:15 +02001096 net = self.conn_vnet.subnets.get(self.resource_group, netName, resName)
1097
lloretgalleg45220152019-10-29 11:53:49 +01001098 out_nets[net_id] = {
jamartinezv14a823d2019-08-01 11:45:15 +02001099 "status": self.provision_state2osm[net.provisioning_state],
1100 "vim_info": str(net)
tierno84efdc12019-05-29 09:29:01 +00001101 }
1102 except CloudError as e:
lloretgalleg45220152019-10-29 11:53:49 +01001103 if e.error.error and "notfound" in e.error.error.lower():
1104 self.logger.info("Not found subnet net_name: %s, subnet_name: %s", netName, resName)
tierno84efdc12019-05-29 09:29:01 +00001105 out_nets[net_id] = {
1106 "status": "DELETED",
jamartinezv14a823d2019-08-01 11:45:15 +02001107 "error_msg": str(e)
tierno84efdc12019-05-29 09:29:01 +00001108 }
1109 else:
lloretgalleg45220152019-10-29 11:53:49 +01001110 self.logger.error("CloudError Exception %s when searching subnet", e)
1111 out_nets[net_id] = {
1112 "status": "VIM_ERROR",
1113 "error_msg": str(e)
1114 }
jamartinezv14a823d2019-08-01 11:45:15 +02001115 except vimconn.vimconnNotFoundException as e:
lloretgalleg45220152019-10-29 11:53:49 +01001116 self.logger.error("VimConnNotFoundException %s when searching subnet", e)
jamartinezv14a823d2019-08-01 11:45:15 +02001117 out_nets[net_id] = {
1118 "status": "DELETED",
1119 "error_msg": str(e)
1120 }
tierno84efdc12019-05-29 09:29:01 +00001121 except Exception as e:
lloretgalleg45220152019-10-29 11:53:49 +01001122 self.logger.error("Exception %s when searching subnet", e, exc_info=True)
tierno84efdc12019-05-29 09:29:01 +00001123 out_nets[net_id] = {
1124 "status": "VIM_ERROR",
tierno84efdc12019-05-29 09:29:01 +00001125 "error_msg": str(e)
1126 }
tierno84efdc12019-05-29 09:29:01 +00001127 return out_nets
1128
1129 def refresh_vms_status(self, vm_list):
lloretgalleg45220152019-10-29 11:53:49 +01001130 """ Get the status of the virtual machines and their interfaces/ports
1131 Params: the list of VM identifiers
1132 Returns a dictionary with:
1133 vm_id: # VIM id of this Virtual Machine
1134 status: # Mandatory. Text with one of:
1135 # DELETED (not found at vim)
1136 # VIM_ERROR (Cannot connect to VIM, VIM response error, ...)
1137 # OTHER (Vim reported other status not understood)
1138 # ERROR (VIM indicates an ERROR status)
1139 # ACTIVE, PAUSED, SUSPENDED, INACTIVE (not running),
1140 # BUILD (on building process), ERROR
1141 # ACTIVE:NoMgmtIP (Active but none of its interfaces has an IP address
1142 # (ACTIVE:NoMgmtIP is not returned for Azure)
1143 #
1144 error_msg: #Text with VIM error message, if any. Or the VIM connection ERROR
1145 vim_info: #Text with plain information obtained from vim (yaml.safe_dump)
1146 interfaces: list with interface info. Each item a dictionary with:
1147 vim_interface_id - The ID of the interface
1148 mac_address - The MAC address of the interface.
1149 ip_address - The IP address of the interface within the subnet.
1150 """
jamartinezv14a823d2019-08-01 11:45:15 +02001151
tierno84efdc12019-05-29 09:29:01 +00001152 out_vms = {}
1153 self._reload_connection()
jamartinezv14a823d2019-08-01 11:45:15 +02001154
lloretgalleg45220152019-10-29 11:53:49 +01001155 self.logger.debug("refresh vm status vm_list: %s", vm_list)
1156 search_vm_list = vm_list or {}
1157
1158 for vm_id in search_vm_list:
1159 out_vm = {}
tierno84efdc12019-05-29 09:29:01 +00001160 try:
lloretgalleg45220152019-10-29 11:53:49 +01001161 res_name = self._get_resource_name_from_resource_id(vm_id)
jamartinezv14a823d2019-08-01 11:45:15 +02001162
lloretgalleg45220152019-10-29 11:53:49 +01001163 vm = self.conn_compute.virtual_machines.get(self.resource_group, res_name)
1164 out_vm['vim_info'] = str(vm)
1165 out_vm['status'] = self.provision_state2osm.get(vm.provisioning_state, 'OTHER')
1166 if vm.provisioning_state == 'Succeeded':
1167 # check if machine is running or stopped
1168 instance_view = self.conn_compute.virtual_machines.instance_view(self.resource_group,
1169 res_name)
1170 for status in instance_view.statuses:
1171 splitted_status = status.code.split("/")
1172 if len(splitted_status) == 2 and splitted_status[0] == 'PowerState':
1173 out_vm['status'] = self.power_state2osm.get(splitted_status[1], 'OTHER')
jamartinezv14a823d2019-08-01 11:45:15 +02001174
1175 network_interfaces = vm.network_profile.network_interfaces
lloretgalleg45220152019-10-29 11:53:49 +01001176 out_vm['interfaces'] = self._get_vm_interfaces_status(vm_id, network_interfaces)
jamartinezv14a823d2019-08-01 11:45:15 +02001177
lloretgalleg45220152019-10-29 11:53:49 +01001178 except CloudError as e:
1179 if e.error.error and "notfound" in e.error.error.lower():
1180 self.logger.debug("Not found vm id: %s", vm_id)
1181 out_vm['status'] = "DELETED"
1182 out_vm['error_msg'] = str(e)
1183 out_vm['vim_info'] = None
1184 else:
1185 # maybe connection error or another type of error, return vim error
1186 self.logger.error("Exception %s refreshing vm_status", e)
1187 out_vm['status'] = "VIM_ERROR"
1188 out_vm['error_msg'] = str(e)
1189 out_vm['vim_info'] = None
tierno84efdc12019-05-29 09:29:01 +00001190 except Exception as e:
lloretgalleg45220152019-10-29 11:53:49 +01001191 self.logger.error("Exception %s refreshing vm_status", e, exc_info=True)
1192 out_vm['status'] = "VIM_ERROR"
1193 out_vm['error_msg'] = str(e)
1194 out_vm['vim_info'] = None
jamartinezv14a823d2019-08-01 11:45:15 +02001195
lloretgalleg45220152019-10-29 11:53:49 +01001196 out_vms[vm_id] = out_vm
tierno84efdc12019-05-29 09:29:01 +00001197
1198 return out_vms
seryio07ad1362019-05-29 09:16:24 +02001199
lloretgalleg45220152019-10-29 11:53:49 +01001200 def _get_vm_interfaces_status(self, vm_id, interfaces):
1201 """
1202 Gets the interfaces detail for a vm
1203 :param interfaces: List of interfaces.
1204 :return: Dictionary with list of interfaces including, vim_interface_id, mac_address and ip_address
1205 """
1206 try:
1207 interface_list = []
1208 for network_interface in interfaces:
1209 interface_dict = {}
1210 nic_name = self._get_resource_name_from_resource_id(network_interface.id)
1211 interface_dict['vim_interface_id'] = network_interface.id
1212
1213 nic_data = self.conn_vnet.network_interfaces.get(
1214 self.resource_group,
1215 nic_name)
1216
lloretgallegbfc28b02019-11-21 09:31:16 +01001217 ips = []
1218 if nic_data.ip_configurations[0].public_ip_address:
1219 self.logger.debug("Obtain public ip address")
1220 public_ip_name = self._get_resource_name_from_resource_id(nic_data.ip_configurations[0].public_ip_address.id)
1221 public_ip = self.conn_vnet.public_ip_addresses.get(self.resource_group, public_ip_name)
1222 self.logger.debug("Public ip address is: %s", public_ip.ip_address)
1223 ips.append(public_ip.ip_address)
1224
lloretgalleg45220152019-10-29 11:53:49 +01001225 private_ip = nic_data.ip_configurations[0].private_ip_address
lloretgallegbfc28b02019-11-21 09:31:16 +01001226 ips.append(private_ip)
lloretgalleg45220152019-10-29 11:53:49 +01001227
1228 interface_dict['mac_address'] = nic_data.mac_address
lloretgallegbfc28b02019-11-21 09:31:16 +01001229 interface_dict['ip_address'] = ";".join(ips)
lloretgalleg45220152019-10-29 11:53:49 +01001230 interface_list.append(interface_dict)
1231
1232 return interface_list
1233 except Exception as e:
1234 self.logger.error("Exception %s obtaining interface data for vm: %s, error: %s", vm_id, e, exc_info=True)
1235 self._format_vimconn_exception(e)
1236
seryio34478552019-05-23 14:50:49 +02001237
1238if __name__ == "__main__":
1239
1240 # Making some basic test
lloretgalleg45220152019-10-29 11:53:49 +01001241 vim_id = 'azure'
1242 vim_name = 'azure'
seryio34478552019-05-23 14:50:49 +02001243 needed_test_params = {
tiernodeb74b22019-05-27 10:24:50 +00001244 "client_id": "AZURE_CLIENT_ID",
1245 "secret": "AZURE_SECRET",
1246 "tenant": "AZURE_TENANT",
1247 "resource_group": "AZURE_RESOURCE_GROUP",
1248 "subscription_id": "AZURE_SUBSCRIPTION_ID",
tierno30d0d6d2019-05-27 08:14:01 +00001249 "vnet_name": "AZURE_VNET_NAME",
seryio34478552019-05-23 14:50:49 +02001250 }
1251 test_params = {}
1252
1253 for param, env_var in needed_test_params.items():
1254 value = getenv(env_var)
1255 if not value:
1256 raise Exception("Provide a valid value for env '{}'".format(env_var))
1257 test_params[param] = value
1258
1259 config = {
1260 'region_name': getenv("AZURE_REGION_NAME", 'westeurope'),
1261 'resource_group': getenv("AZURE_RESOURCE_GROUP"),
1262 'subscription_id': getenv("AZURE_SUBSCRIPTION_ID"),
tierno30d0d6d2019-05-27 08:14:01 +00001263 'pub_key': getenv("AZURE_PUB_KEY", None),
seryio34478552019-05-23 14:50:49 +02001264 'vnet_name': getenv("AZURE_VNET_NAME", 'myNetwork'),
1265 }
tierno30d0d6d2019-05-27 08:14:01 +00001266
seryio34478552019-05-23 14:50:49 +02001267 virtualMachine = {
tierno30d0d6d2019-05-27 08:14:01 +00001268 'name': 'sergio',
1269 'description': 'new VM',
seryio34478552019-05-23 14:50:49 +02001270 'status': 'running',
1271 'image': {
1272 'publisher': 'Canonical',
1273 'offer': 'UbuntuServer',
1274 'sku': '16.04.0-LTS',
1275 'version': 'latest'
1276 },
1277 'hardware_profile': {
1278 'vm_size': 'Standard_DS1_v2'
1279 },
1280 'networks': [
1281 'sergio'
1282 ]
1283 }
1284
1285 vnet_config = {
1286 'subnet_address': '10.1.2.0/24',
1287 #'subnet_name': 'subnet-oam'
1288 }
1289 ###########################
1290
tierno30d0d6d2019-05-27 08:14:01 +00001291 azure = vimconnector(vim_id, vim_name, tenant_id=test_params["tenant"], tenant_name=None, url=None, url_admin=None,
1292 user=test_params["client_id"], passwd=test_params["secret"], log_level=None, config=config)
seryio34478552019-05-23 14:50:49 +02001293
tiernodeb74b22019-05-27 10:24:50 +00001294 # azure.get_flavor_id_from_data("here")
1295 # subnets=azure.get_network_list()
1296 # azure.new_vminstance(virtualMachine['name'], virtualMachine['description'], virtualMachine['status'],
1297 # virtualMachine['image'], virtualMachine['hardware_profile']['vm_size'], subnets)
1298
tierno24620412019-06-03 14:05:08 +00001299 azure.new_network("mynet", None)
tierno84efdc12019-05-29 09:29:01 +00001300 net_id = "/subscriptions/82f80cc1-876b-4591-9911-1fb5788384fd/resourceGroups/osmRG/providers/Microsoft."\
1301 "Network/virtualNetworks/test"
1302 net_id_not_found = "/subscriptions/82f80cc1-876b-4591-9911-1fb5788384fd/resourceGroups/osmRG/providers/"\
1303 "Microsoft.Network/virtualNetworks/testALF"
1304 azure.refresh_nets_status([net_id, net_id_not_found])