1 # -*- coding: utf-8 -*-
4 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
5 # This file is part of openmano
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
25 NFVO engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances
27 __author__
="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
28 __date__
="$16-sep-2014 22:05:01$"
34 from db_base
import HTTP_Unauthorized
, HTTP_Bad_Request
, HTTP_Internal_Server_Error
, HTTP_Not_Found
,\
35 HTTP_Conflict
, HTTP_Method_Not_Allowed
36 import console_proxy_thread
as cli
40 from db_base
import db_base_Exception
43 global vimconn_imported
45 global default_volume_size
46 default_volume_size
= '5' #size in GB
49 vimconn_imported
={} #dictionary with VIM type as key, loaded module as value
50 logger
= logging
.getLogger('openmano.nfvo')
52 class NfvoException(Exception):
53 def __init__(self
, message
, http_code
):
54 self
.http_code
= http_code
55 Exception.__init
__(self
, message
)
58 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
60 return result, content:
61 <0, error_text upon error
62 nb_records, flavor_list on success
65 WHERE_dict
['vnf_id'] = vnf_id
66 if nfvo_tenant
is not None:
67 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
69 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
70 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
71 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
72 #print "get_flavor_list result:", result
73 #print "get_flavor_list content:", content
75 for flavor
in flavors
:
76 flavorList
.append(flavor
['flavor_id'])
79 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
81 return result, content:
82 <0, error_text upon error
83 nb_records, flavor_list on success
86 WHERE_dict
['vnf_id'] = vnf_id
87 if nfvo_tenant
is not None:
88 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
90 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
91 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
94 imageList
.append(image
['image_id'])
97 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
98 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
99 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
100 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
101 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
102 raise exception upon error
105 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
106 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
107 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
108 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
109 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
110 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
111 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
112 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
113 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
114 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
115 'user','passwd', 'dt.config as dt_config')
117 from_
= 'datacenters as d'
118 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
120 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
123 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
125 extra
.update(yaml
.load(vim
["config"]))
126 if vim
.get('dt_config'):
127 extra
.update(yaml
.load(vim
["dt_config"]))
128 if vim
["type"] not in vimconn_imported
:
131 module
= "vimconn_" + vim
["type"]
132 module_info
= imp
.find_module(module
)
133 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
134 vimconn_imported
[vim
["type"]] = vim_conn
135 except (IOError, ImportError) as e
:
136 if module_info
and module_info
[0]:
137 file.close(module_info
[0])
138 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
139 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
143 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
144 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
145 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
146 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
), tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
147 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
148 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
151 except Exception as e
:
152 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
154 except db_base_Exception
as e
:
155 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
157 def rollback(mydb
, vims
, rollback_list
):
159 #delete things by reverse order
160 for i
in range(len(rollback_list
)-1, -1, -1):
161 item
= rollback_list
[i
]
162 if item
["where"]=="vim":
163 if item
["vim_id"] not in vims
:
165 vim
=vims
[ item
["vim_id"] ]
167 if item
["what"]=="image":
168 vim
.delete_image(item
["uuid"])
169 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
170 elif item
["what"]=="flavor":
171 vim
.delete_flavor(item
["uuid"])
172 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
173 elif item
["what"]=="network":
174 vim
.delete_network(item
["uuid"])
175 elif item
["what"]=="vm":
176 vim
.delete_vminstance(item
["uuid"])
177 except vimconn
.vimconnException
as e
:
178 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
179 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
180 except db_base_Exception
as e
:
181 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
185 if item
["what"]=="image":
186 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
187 elif item
["what"]=="flavor":
188 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
189 except db_base_Exception
as e
:
190 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
191 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
192 if len(undeleted_items
)==0:
193 return True," Rollback successful."
195 return False," Rollback fails to delete: " + str(undeleted_items
)
197 def check_vnf_descriptor(vnf_descriptor
):
199 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
201 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
203 #dataplane interfaces
204 for numa
in vnfc
.get("numas",() ):
205 for interface
in numa
.get("interfaces",()):
206 if interface
["name"] in name_list
:
207 raise NfvoException("Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC"\
208 .format(vnfc
["name"], interface
["name"]),
210 name_list
.append( interface
["name"] )
212 for interface
in vnfc
.get("bridge-ifaces",() ):
213 if interface
["name"] in name_list
:
214 raise NfvoException("Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC"\
215 .format(vnfc
["name"], interface
["name"]),
217 name_list
.append( interface
["name"] )
218 vnfc_interfaces
[ vnfc
["name"] ] = name_list
220 #check if the info in external_connections matches with the one in the vnfcs
222 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
223 if external_connection
["name"] in name_list
:
224 raise NfvoException("Error at vnf:external-connections:name, value '{}' already used as an external-connection"\
225 .format(external_connection
["name"]),
227 name_list
.append(external_connection
["name"])
228 if external_connection
["VNFC"] not in vnfc_interfaces
:
229 raise NfvoException("Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC"\
230 .format(external_connection
["name"], external_connection
["VNFC"]),
233 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
234 raise NfvoException("Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC"\
235 .format(external_connection
["name"], external_connection
["local_iface_name"]),
238 #check if the info in internal_connections matches with the one in the vnfcs
240 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
241 if internal_connection
["name"] in name_list
:
242 raise NfvoException("Error at vnf:internal-connections:name, value '%s' already used as an internal-connection"\
243 .format(internal_connection
["name"]),
245 name_list
.append(internal_connection
["name"])
246 #We should check that internal-connections of type "ptp" have only 2 elements
247 if len(internal_connection
["elements"])>2 and internal_connection
["type"] == "ptp":
248 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements, size must be 2 for a type:'ptp'"\
249 .format(internal_connection
["name"]),
251 for port
in internal_connection
["elements"]:
252 if port
["VNFC"] not in vnfc_interfaces
:
253 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC"\
254 .format(internal_connection
["name"], port
["VNFC"]),
256 if port
["local_iface_name"] not in vnfc_interfaces
[ port
["VNFC"] ]:
257 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC"\
258 .format(internal_connection
["name"], port
["local_iface_name"]),
260 return -HTTP_Bad_Request
,
262 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
264 if only_create_at_vim
:
265 image_mano_id
= image_dict
['uuid']
266 if return_on_error
== None:
267 return_on_error
= True
269 if image_dict
['location']:
270 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
272 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
274 image_mano_id
= images
[0]['uuid']
276 #create image in MANO DB
277 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
278 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
279 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
281 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
282 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
283 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
284 #create image at every vim
285 for vim_id
,vim
in vims
.iteritems():
286 image_created
="false"
288 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
289 #look at VIM if this image exist
291 if image_dict
['location'] is not None:
292 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
295 filter_dict
['name'] = image_dict
['universal_name']
296 if image_dict
.get('checksum') != None:
297 filter_dict
['checksum'] = image_dict
['checksum']
298 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
299 vim_images
= vim
.get_image_list(filter_dict
)
300 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
301 if len(vim_images
) > 1:
302 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), HTTP_Conflict
)
303 elif len(vim_images
) == 0:
304 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
306 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
307 image_vim_id
= vim_images
[0]['id']
309 except vimconn
.vimconnNotFoundException
as e
:
310 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
312 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
313 if image_dict
['location']:
314 image_vim_id
= vim
.new_image(image_dict
)
315 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
318 raise vimconn
.vimconnException("Cannot create image without location")
319 except vimconn
.vimconnException
as e
:
321 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
324 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
326 except vimconn
.vimconnException
as e
:
328 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
330 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
333 #if we reach here, the image has been created or existed
335 #add new vim_id at datacenters_images
336 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
337 elif image_db
[0]["vim_id"]!=image_vim_id
:
338 #modify existing vim_id at datacenters_images
339 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
341 return image_vim_id
if only_create_at_vim
else image_mano_id
343 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
344 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
345 'ram':flavor_dict
.get('ram'),
346 'vcpus':flavor_dict
.get('vcpus'),
348 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
349 del flavor_dict
['extended']
350 if 'extended' in flavor_dict
:
351 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
353 #look if flavor exist
354 if only_create_at_vim
:
355 flavor_mano_id
= flavor_dict
['uuid']
356 if return_on_error
== None:
357 return_on_error
= True
359 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
361 flavor_mano_id
= flavors
[0]['uuid']
364 #create one by one the images of aditional disks
365 dev_image_list
=[] #list of images
366 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
368 for device
in flavor_dict
['extended'].get('devices',[]):
369 if "image" not in device
and "image name" not in device
:
372 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
373 image_dict
['universal_name']=device
.get('image name')
374 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
375 image_dict
['location']=device
.get('image')
376 #image_dict['new_location']=vnfc.get('image location')
377 image_dict
['checksum']=device
.get('image checksum')
378 image_metadata_dict
= device
.get('image metadata', None)
379 image_metadata_str
= None
380 if image_metadata_dict
!= None:
381 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
382 image_dict
['metadata']=image_metadata_str
383 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
384 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
385 dev_image_list
.append(image_id
)
387 temp_flavor_dict
['name'] = flavor_dict
['name']
388 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
389 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
390 flavor_mano_id
= content
391 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
392 #create flavor at every vim
393 if 'uuid' in flavor_dict
:
394 del flavor_dict
['uuid']
396 for vim_id
,vim
in vims
.items():
397 flavor_created
="false"
399 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
400 #look at VIM if this flavor exist SKIPPED
401 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
403 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
407 #Create the flavor in VIM
408 #Translate images at devices from MANO id to VIM id
410 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
411 #make a copy of original devices
414 for device
in flavor_dict
["extended"].get("devices",[]):
417 devices_original
.append(dev
)
418 if 'image' in device
:
420 if 'image metadata' in device
:
421 del device
['image metadata']
423 for index
in range(0,len(devices_original
)) :
424 device
=devices_original
[index
]
425 if "image" not in device
and "image name" not in device
:
427 disk_list
.append({'size': device
.get('size', default_volume_size
)})
430 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
431 image_dict
['universal_name']=device
.get('image name')
432 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
433 image_dict
['location']=device
.get('image')
434 #image_dict['new_location']=device.get('image location')
435 image_dict
['checksum']=device
.get('image checksum')
436 image_metadata_dict
= device
.get('image metadata', None)
437 image_metadata_str
= None
438 if image_metadata_dict
!= None:
439 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
440 image_dict
['metadata']=image_metadata_str
441 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
442 image_dict
["uuid"]=image_mano_id
443 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
445 #save disk information (image must be based on and size
446 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
448 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
451 #check that this vim_id exist in VIM, if not create
452 flavor_vim_id
=flavor_db
[0]["vim_id"]
454 vim
.get_flavor(flavor_vim_id
)
455 continue #flavor exist
456 except vimconn
.vimconnException
:
458 #create flavor at vim
459 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
461 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
462 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
463 flavor_created
="true"
464 except vimconn
.vimconnException
as e
:
466 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
468 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
471 #if reach here the flavor has been create or exist
472 if len(flavor_db
)==0:
473 #add new vim_id at datacenters_flavors
474 extended_devices_yaml
= None
475 if len(disk_list
) > 0:
476 extended_devices
= dict()
477 extended_devices
['disks'] = disk_list
478 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
479 mydb
.new_row('datacenters_flavors',
480 {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
,
481 'created':flavor_created
,'extended': extended_devices_yaml
})
482 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
483 #modify existing vim_id at datacenters_flavors
484 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
486 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
488 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
491 # Step 1. Check the VNF descriptor
492 check_vnf_descriptor(vnf_descriptor
)
493 # Step 2. Check tenant exist
494 if tenant_id
!= "any":
495 check_tenant(mydb
, tenant_id
)
496 if "tenant_id" in vnf_descriptor
["vnf"]:
497 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
498 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
501 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
502 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
503 vims
= get_vim(mydb
, tenant_id
)
507 # Step 4. Review the descriptor and add missing fields
508 #print vnf_descriptor
509 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
510 vnf_name
= vnf_descriptor
['vnf']['name']
511 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
512 if "physical" in vnf_descriptor
['vnf']:
513 del vnf_descriptor
['vnf']['physical']
514 #print vnf_descriptor
515 # Step 5. Check internal connections
516 # TODO: to be moved to step 1????
517 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
518 for ic
in internal_connections
:
519 if len(ic
['elements'])>2 and ic
['type']=='ptp':
520 raise NfvoException("Mismatch 'type':'ptp' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'data'".format(len(ic
), ic
['name']),
522 elif len(ic
['elements'])==2 and ic
['type']=='data':
523 raise NfvoException("Mismatch 'type':'data' with 2 elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'ptp'".format(ic
['name']),
526 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
527 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
528 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
530 #For each VNFC, we add it to the VNFCDict and we create a flavor.
531 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
532 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
534 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
535 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
537 VNFCitem
["name"] = vnfc
['name']
538 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
540 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
543 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
544 myflavorDict
["description"] = VNFCitem
["description"]
545 myflavorDict
["ram"] = vnfc
.get("ram", 0)
546 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
547 myflavorDict
["disk"] = vnfc
.get("disk", 1)
548 myflavorDict
["extended"] = {}
550 devices
= vnfc
.get("devices")
552 myflavorDict
["extended"]["devices"] = devices
555 # Mapping from processor models to rankings should be available somehow in the NFVO. They could be taken from VIM or directly from a new database table
556 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
558 # Previous code has been commented
559 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
560 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
561 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
562 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
564 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
566 # print "Error creating flavor: unknown processor model. Rollback successful."
567 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
569 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
570 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
572 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
573 myflavorDict
['extended']['numas'] = vnfc
['numas']
577 # Step 6.2 New flavors are created in the VIM
578 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
580 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
581 VNFCitem
["flavor_id"] = flavor_id
582 VNFCDict
[vnfc
['name']] = VNFCitem
584 logger
.debug("Creating new images in the VIM for each VNFC")
585 # Step 6.3 New images are created in the VIM
586 #For each VNFC, we must create the appropriate image.
587 #This "for" loop might be integrated with the previous one
588 #In case this integration is made, the VNFCDict might become a VNFClist.
589 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
590 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
592 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
593 image_dict
['universal_name']=vnfc
.get('image name')
594 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
595 image_dict
['location']=vnfc
.get('VNFC image')
596 #image_dict['new_location']=vnfc.get('image location')
597 image_dict
['checksum']=vnfc
.get('image checksum')
598 image_metadata_dict
= vnfc
.get('image metadata', None)
599 image_metadata_str
= None
600 if image_metadata_dict
is not None:
601 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
602 image_dict
['metadata']=image_metadata_str
603 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
604 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
605 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
606 VNFCDict
[vnfc
['name']]["image_id"] = image_id
607 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
610 # Step 7. Storing the VNF descriptor in the repository
611 if "descriptor" not in vnf_descriptor
["vnf"]:
612 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
614 # Step 8. Adding the VNF to the NFVO DB
615 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
617 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
618 _
, message
= rollback(mydb
, vims
, rollback_list
)
619 if isinstance(e
, db_base_Exception
):
620 error_text
= "Exception at database"
621 elif isinstance(e
, KeyError):
622 error_text
= "KeyError exception "
623 e
.http_code
= HTTP_Internal_Server_Error
625 error_text
= "Exception at VIM"
626 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
627 #logger.error("start_scenario %s", error_text)
628 raise NfvoException(error_text
, e
.http_code
)
630 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
633 # Step 1. Check the VNF descriptor
634 check_vnf_descriptor(vnf_descriptor
)
635 # Step 2. Check tenant exist
636 if tenant_id
!= "any":
637 check_tenant(mydb
, tenant_id
)
638 if "tenant_id" in vnf_descriptor
["vnf"]:
639 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
640 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
643 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
644 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
645 vims
= get_vim(mydb
, tenant_id
)
649 # Step 4. Review the descriptor and add missing fields
650 #print vnf_descriptor
651 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
652 vnf_name
= vnf_descriptor
['vnf']['name']
653 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
654 if "physical" in vnf_descriptor
['vnf']:
655 del vnf_descriptor
['vnf']['physical']
656 #print vnf_descriptor
657 # Step 5. Check internal connections
658 # TODO: to be moved to step 1????
659 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
660 for ic
in internal_connections
:
661 if len(ic
['elements'])>2 and ic
['type']=='e-line':
662 raise NfvoException("Mismatch 'type':'e-line' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'e-lan'".format(len(ic
), ic
['name']),
665 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
666 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
667 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
669 #For each VNFC, we add it to the VNFCDict and we create a flavor.
670 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
671 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
673 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
674 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
676 VNFCitem
["name"] = vnfc
['name']
677 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
679 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
682 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
683 myflavorDict
["description"] = VNFCitem
["description"]
684 myflavorDict
["ram"] = vnfc
.get("ram", 0)
685 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
686 myflavorDict
["disk"] = vnfc
.get("disk", 1)
687 myflavorDict
["extended"] = {}
689 devices
= vnfc
.get("devices")
691 myflavorDict
["extended"]["devices"] = devices
694 # Mapping from processor models to rankings should be available somehow in the NFVO. They could be taken from VIM or directly from a new database table
695 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
697 # Previous code has been commented
698 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
699 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
700 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
701 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
703 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
705 # print "Error creating flavor: unknown processor model. Rollback successful."
706 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
708 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
709 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
711 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
712 myflavorDict
['extended']['numas'] = vnfc
['numas']
716 # Step 6.2 New flavors are created in the VIM
717 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
719 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
720 VNFCitem
["flavor_id"] = flavor_id
721 VNFCDict
[vnfc
['name']] = VNFCitem
723 logger
.debug("Creating new images in the VIM for each VNFC")
724 # Step 6.3 New images are created in the VIM
725 #For each VNFC, we must create the appropriate image.
726 #This "for" loop might be integrated with the previous one
727 #In case this integration is made, the VNFCDict might become a VNFClist.
728 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
729 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
731 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
732 image_dict
['universal_name']=vnfc
.get('image name')
733 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
734 image_dict
['location']=vnfc
.get('VNFC image')
735 #image_dict['new_location']=vnfc.get('image location')
736 image_dict
['checksum']=vnfc
.get('image checksum')
737 image_metadata_dict
= vnfc
.get('image metadata', None)
738 image_metadata_str
= None
739 if image_metadata_dict
is not None:
740 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
741 image_dict
['metadata']=image_metadata_str
742 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
743 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
744 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
745 VNFCDict
[vnfc
['name']]["image_id"] = image_id
746 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
749 # Step 7. Storing the VNF descriptor in the repository
750 if "descriptor" not in vnf_descriptor
["vnf"]:
751 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
753 # Step 8. Adding the VNF to the NFVO DB
754 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
756 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
757 _
, message
= rollback(mydb
, vims
, rollback_list
)
758 if isinstance(e
, db_base_Exception
):
759 error_text
= "Exception at database"
760 elif isinstance(e
, KeyError):
761 error_text
= "KeyError exception "
762 e
.http_code
= HTTP_Internal_Server_Error
764 error_text
= "Exception at VIM"
765 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
766 #logger.error("start_scenario %s", error_text)
767 raise NfvoException(error_text
, e
.http_code
)
769 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
770 #check valid tenant_id
771 check_tenant(mydb
, tenant_id
)
774 if tenant_id
!= "any":
775 where_or
["tenant_id"] = tenant_id
776 where_or
["public"] = True
777 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
780 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
781 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
782 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
783 data
={'vnf' : filtered_content
}
785 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
786 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description'),
787 WHERE
={'vnfs.uuid': vnf_id
} )
789 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
791 data
['vnf']['VNFC'] = content
792 #TODO: GET all the information from a VNFC and include it in the output.
795 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
796 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
797 WHERE
={'vnfs.uuid': vnf_id
} )
798 data
['vnf']['nets'] = content
800 #GET ip-profile for each net
801 for net
in data
['vnf']['nets']:
802 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
803 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
804 WHERE
={'net_id': net
["uuid"]} )
805 if len(ipprofiles
)==1:
806 net
["ip_profile"] = ipprofiles
[0]
807 elif len(ipprofiles
)>1:
808 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
811 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
813 #GET External Interfaces
814 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
815 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
816 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
817 WHERE
={'vnfs.uuid': vnf_id
},
818 WHERE_NOT
={'interfaces.external_name': None} )
820 data
['vnf']['external-connections'] = content
825 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
827 if tenant_id
!= "any":
828 check_tenant(mydb
, tenant_id
)
829 # Get the URL of the VIM from the nfvo_tenant and the datacenter
830 vims
= get_vim(mydb
, tenant_id
)
834 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
836 if tenant_id
!= "any":
837 where_or
["tenant_id"] = tenant_id
838 where_or
["public"] = True
839 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
842 # "Getting the list of flavors and tenants of the VNF"
843 flavorList
= get_flavorlist(mydb
, vnf_id
)
844 if len(flavorList
)==0:
845 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
847 imageList
= get_imagelist(mydb
, vnf_id
)
848 if len(imageList
)==0:
849 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
851 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
853 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
856 for flavor
in flavorList
:
857 #check if flavor is used by other vnf
859 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
861 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
863 #flavor not used, must be deleted
865 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
867 if flavor_vim
["datacenter_id"] not in vims
:
869 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
871 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
873 myvim
.delete_flavor(flavor_vim
["vim_id"])
874 except vimconn
.vimconnNotFoundException
as e
:
875 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
876 except vimconn
.vimconnException
as e
:
877 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
878 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
879 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
880 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
881 mydb
.delete_row_by_id('flavors', flavor
)
882 except db_base_Exception
as e
:
883 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
884 undeletedItems
.append("flavor %s" % flavor
)
887 for image
in imageList
:
889 #check if image is used by other vnf
890 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
892 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
894 #image not used, must be deleted
896 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
898 if image_vim
["datacenter_id"] not in vims
:
900 if image_vim
['created']=='false': #skip this image because not created by openmano
902 myvim
=vims
[ image_vim
["datacenter_id"] ]
904 myvim
.delete_image(image_vim
["vim_id"])
905 except vimconn
.vimconnNotFoundException
as e
:
906 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
907 except vimconn
.vimconnException
as e
:
908 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
909 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
910 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
911 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
912 mydb
.delete_row_by_id('images', image
)
913 except db_base_Exception
as e
:
914 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
915 undeletedItems
.append("image %s" % image
)
917 return vnf_id
+ " " + vnf
["name"]
919 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
921 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
922 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
926 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
927 myvim
= vims
.values()[0]
928 result
,servers
= myvim
.get_hosts_info()
930 return result
, servers
931 topology
= {'name':myvim
['name'] , 'servers': servers
}
932 return result
, topology
934 def get_hosts(mydb
, nfvo_tenant_id
):
935 vims
= get_vim(mydb
, nfvo_tenant_id
)
937 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
939 #print "nfvo.datacenter_action() error. Several datacenters found"
940 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
941 myvim
= vims
.values()[0]
943 hosts
= myvim
.get_hosts()
944 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
946 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
948 server
={'name':host
['name'], 'vms':[]}
949 for vm
in host
['instances']:
950 #get internal name and model
952 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
953 WHERE
={'vim_vm_id':vm
['id']} )
955 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
957 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
959 except db_base_Exception
as e
:
960 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
961 datacenter
['Datacenters'][0]['servers'].append(server
)
962 #return -400, "en construccion"
964 #print 'datacenters '+ json.dumps(datacenter, indent=4)
966 except vimconn
.vimconnException
as e
:
967 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
969 def new_scenario(mydb
, tenant_id
, topo
):
971 # result, vims = get_vim(mydb, tenant_id)
973 # return result, vims
975 if tenant_id
!= "any":
976 check_tenant(mydb
, tenant_id
)
977 if "tenant_id" in topo
:
978 if topo
["tenant_id"] != tenant_id
:
979 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
984 #1.1: get VNFs and external_networks (other_nets).
986 other_nets
={} #external_networks, bridge_networks and data_networkds
987 nodes
= topo
['topology']['nodes']
988 for k
in nodes
.keys():
989 if nodes
[k
]['type'] == 'VNF':
991 vnfs
[k
]['ifaces'] = {}
992 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
993 other_nets
[k
] = nodes
[k
]
994 other_nets
[k
]['external']=True
995 elif nodes
[k
]['type'] == 'network':
996 other_nets
[k
] = nodes
[k
]
997 other_nets
[k
]['external']=False
1000 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1001 for name
,vnf
in vnfs
.items():
1003 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1005 error_pos
= "'topology':'nodes':'" + name
+ "'"
1007 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1008 where
['uuid'] = vnf
['vnf_id']
1009 if 'VNF model' in vnf
:
1010 error_text
+= " 'VNF model' " + vnf
['VNF model']
1011 where
['name'] = vnf
['VNF model']
1013 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1015 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1021 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1023 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1024 vnf
['uuid']=vnf_db
[0]['uuid']
1025 vnf
['description']=vnf_db
[0]['description']
1026 #get external interfaces
1027 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1028 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1029 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1030 for ext_iface
in ext_ifaces
:
1031 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1033 #1.4 get list of connections
1034 conections
= topo
['topology']['connections']
1035 conections_list
= []
1036 conections_list_name
= []
1037 for k
in conections
.keys():
1038 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1039 ifaces_list
= conections
[k
]['nodes'].items()
1040 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1042 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1043 for k2
in conection_pair_list
:
1046 con_type
= conections
[k
].get("type", "link")
1047 if con_type
!= "link":
1049 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1050 other_nets
[k
] = {'external': False}
1051 if conections
[k
].get("graph"):
1052 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1053 ifaces_list
.append( (k
, None) )
1056 if con_type
== "external_network":
1057 other_nets
[k
]['external'] = True
1058 if conections
[k
].get("model"):
1059 other_nets
[k
]["model"] = conections
[k
]["model"]
1061 other_nets
[k
]["model"] = k
1062 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1063 other_nets
[k
]["model"] = con_type
1065 conections_list_name
.append(k
)
1066 conections_list
.append(set(ifaces_list
)) #from list to set to operate as a set (this conversion removes elements that are repeated in a list)
1067 #print set(ifaces_list)
1068 #check valid VNF and iface names
1069 for iface
in ifaces_list
:
1070 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1071 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1072 str(k
), iface
[0]), HTTP_Not_Found
)
1073 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1074 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1075 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1077 #1.5 unify connections from the pair list to a consolidated list
1079 while index
< len(conections_list
):
1081 while index2
< len(conections_list
):
1082 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1083 conections_list
[index
] |
= conections_list
[index2
]
1084 del conections_list
[index2
]
1085 del conections_list_name
[index2
]
1088 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1090 #for k in conections_list:
1095 #1.6 Delete non external nets
1096 # for k in other_nets.keys():
1097 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1098 # for con in conections_list:
1100 # for index in range(0,len(con)):
1101 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1102 # for index in delete_indexes:
1105 #1.7: Check external_ports are present at database table datacenter_nets
1106 for k
,net
in other_nets
.items():
1107 error_pos
= "'topology':'nodes':'" + k
+ "'"
1108 if net
['external']==False:
1109 if 'name' not in net
:
1111 if 'model' not in net
:
1112 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1113 if net
['model']=='bridge_net':
1114 net
['type']='bridge';
1115 elif net
['model']=='dataplane_net':
1118 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1120 #IF we do not want to check that external network exist at datacenter
1125 # if 'net_id' in net:
1126 # error_text += " 'net_id' " + net['net_id']
1127 # WHERE_['uuid'] = net['net_id']
1128 # if 'model' in net:
1129 # error_text += " 'model' " + net['model']
1130 # WHERE_['name'] = net['model']
1131 # if len(WHERE_) == 0:
1132 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1133 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1134 # FROM='datacenter_nets', WHERE=WHERE_ )
1136 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1138 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1139 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1141 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1142 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1143 # other_nets[k].update(net_db[0])
1146 net_nb
=0 #Number of nets
1147 for con
in conections_list
:
1148 #check if this is connected to a external net
1152 for index
in range(0,len(con
)):
1153 #check if this is connected to a external net
1154 for net_key
in other_nets
.keys():
1155 if con
[index
][0]==net_key
:
1156 if other_net_index
>=0:
1157 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1158 #print "nfvo.new_scenario " + error_text
1159 raise NfvoException(error_text
, HTTP_Bad_Request
)
1161 other_net_index
= index
1162 net_target
= net_key
1164 #print "other_net_index", other_net_index
1166 if other_net_index
>=0:
1167 del con
[other_net_index
]
1168 #IF we do not want to check that external network exist at datacenter
1169 if other_nets
[net_target
]['external'] :
1170 if "name" not in other_nets
[net_target
]:
1171 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1172 if other_nets
[net_target
]["type"] == "external_network":
1173 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1174 other_nets
[net_target
]["type"] = "data"
1176 other_nets
[net_target
]["type"] = "bridge"
1178 # if other_nets[net_target]['external'] :
1179 # type_='data' if len(con)>1 else 'ptp' #an external net is connected to a external port, so it is ptp if only one connection is done to this net
1180 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1181 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1182 # print "nfvo.new_scenario " + error_text
1183 # return -HTTP_Bad_Request, error_text
1186 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1189 net_type_bridge
=False
1191 net_target
= "__-__net"+str(net_nb
)
1192 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1193 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1196 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1197 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1198 if iface_type
=='mgmt' or iface_type
=='bridge':
1199 net_type_bridge
= True
1201 net_type_data
= True
1202 if net_type_bridge
and net_type_data
:
1203 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1204 #print "nfvo.new_scenario " + error_text
1205 raise NfvoException(error_text
, HTTP_Bad_Request
)
1206 elif net_type_bridge
:
1209 type_
='data' if len(con
)>2 else 'ptp'
1210 net_list
[net_target
]['type'] = type_
1213 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1214 #print "nfvo.new_scenario " + error_text
1216 raise NfvoException(error_text
, HTTP_Bad_Request
)
1218 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1219 #1.8.1 obtain management net
1220 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1221 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1222 #1.8.2 check all interfaces from all vnfs
1224 add_mgmt_net
= False
1225 for vnf
in vnfs
.values():
1226 for iface
in vnf
['ifaces'].values():
1227 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1228 #iface not connected
1229 iface
['net_key'] = 'mgmt'
1231 if add_mgmt_net
and 'mgmt' not in net_list
:
1232 net_list
['mgmt']=mgmt_net
[0]
1233 net_list
['mgmt']['external']=True
1234 net_list
['mgmt']['graph']={'visible':False}
1236 net_list
.update(other_nets
)
1238 #print 'net_list', net_list
1243 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1244 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1245 'tenant_id':tenant_id
, 'name':topo
['name'],
1246 'description':topo
.get('description',topo
['name']),
1247 'public': topo
.get('public', False)
1252 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
):
1253 scenario
= scenario_dict
["scenario"]
1254 if tenant_id
!= "any":
1255 check_tenant(mydb
, tenant_id
)
1256 if "tenant_id" in scenario
:
1257 if scenario
["tenant_id"] != tenant_id
:
1258 print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1259 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1260 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1264 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1265 for name
,vnf
in scenario
["vnfs"].iteritems():
1267 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1269 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1271 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1272 where
['uuid'] = vnf
['vnf_id']
1273 if 'vnf_name' in vnf
:
1274 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1275 where
['name'] = vnf
['vnf_name']
1277 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1278 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1284 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1286 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1287 vnf
['uuid']=vnf_db
[0]['uuid']
1288 vnf
['description']=vnf_db
[0]['description']
1290 #get external interfaces
1291 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1292 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1293 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1294 for ext_iface
in ext_ifaces
:
1295 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1297 #2: Insert net_key at every vnf interface
1298 for net_name
,net
in scenario
["networks"].iteritems():
1299 net_type_bridge
=False
1301 for iface_dict
in net
["interfaces"]:
1302 for vnf
,iface
in iface_dict
.iteritems():
1303 if vnf
not in scenario
["vnfs"]:
1304 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1305 #print "nfvo.new_scenario_v02 " + error_text
1306 raise NfvoException(error_text
, HTTP_Not_Found
)
1307 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1308 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1309 #print "nfvo.new_scenario_v02 " + error_text
1310 raise NfvoException(error_text
, HTTP_Bad_Request
)
1311 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1312 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1313 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1314 #print "nfvo.new_scenario_v02 " + error_text
1315 raise NfvoException(error_text
, HTTP_Bad_Request
)
1316 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1317 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1318 if iface_type
=='mgmt' or iface_type
=='bridge':
1319 net_type_bridge
= True
1321 net_type_data
= True
1322 if net_type_bridge
and net_type_data
:
1323 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1324 #print "nfvo.new_scenario " + error_text
1325 raise NfvoException(error_text
, HTTP_Bad_Request
)
1326 elif net_type_bridge
:
1329 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1331 net
['name'] = net_name
1332 net
['external'] = net
.get('external', False)
1334 #3: insert at database
1335 scenario
["nets"] = scenario
["networks"]
1336 scenario
['tenant_id'] = tenant_id
1337 scenario_id
= mydb
.new_scenario( scenario
)
1340 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1341 data
["uuid"] = scenario_id
1342 data
["tenant_id"] = tenant_id
1343 c
= mydb
.edit_scenario( data
)
1346 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1347 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1348 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
1349 vims
= {datacenter_id
: myvim
}
1350 myvim_tenant
= myvim
['tenant_id']
1351 datacenter_name
= myvim
['name']
1355 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1356 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1357 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
1358 scenarioDict
['datacenter_id'] = datacenter_id
1359 #print '================scenarioDict======================='
1360 #print json.dumps(scenarioDict, indent=4)
1361 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1363 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1364 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1366 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1367 auxNetDict
['scenario'] = {}
1369 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1370 for sce_net
in scenarioDict
['nets']:
1371 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1373 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1374 myNetName
= myNetName
[0:255] #limit length
1375 myNetType
= sce_net
['type']
1377 myNetDict
["name"] = myNetName
1378 myNetDict
["type"] = myNetType
1379 myNetDict
["tenant_id"] = myvim_tenant
1380 myNetIPProfile
= sce_net
.get('ip_profile', None)
1382 #We should use the dictionary as input parameter for new_network
1384 if not sce_net
["external"]:
1385 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1386 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1387 sce_net
['vim_id'] = network_id
1388 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1389 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1390 sce_net
["created"] = True
1392 if sce_net
['vim_id'] == None:
1393 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1394 _
, message
= rollback(mydb
, vims
, rollbackList
)
1395 logger
.error("nfvo.start_scenario: %s", error_text
)
1396 raise NfvoException(error_text
, HTTP_Bad_Request
)
1397 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1398 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1400 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1401 #For each vnf net, we create it and we add it to instanceNetlist.
1402 for sce_vnf
in scenarioDict
['vnfs']:
1403 for net
in sce_vnf
['nets']:
1404 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1406 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1407 myNetName
= myNetName
[0:255] #limit length
1408 myNetType
= net
['type']
1410 myNetDict
["name"] = myNetName
1411 myNetDict
["type"] = myNetType
1412 myNetDict
["tenant_id"] = myvim_tenant
1413 myNetIPProfile
= net
.get('ip_profile', None)
1416 #We should use the dictionary as input parameter for new_network
1417 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1418 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1419 net
['vim_id'] = network_id
1420 if sce_vnf
['uuid'] not in auxNetDict
:
1421 auxNetDict
[sce_vnf
['uuid']] = {}
1422 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1423 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1424 net
["created"] = True
1426 #print "auxNetDict:"
1427 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1429 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1430 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1432 for sce_vnf
in scenarioDict
['vnfs']:
1433 for vm
in sce_vnf
['vms']:
1436 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1437 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
1438 #myVMDict['description'] = vm['description']
1439 myVMDict
['description'] = myVMDict
['name'][0:99]
1441 myVMDict
['start'] = "no"
1442 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1443 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1445 #create image at vim in case it not exist
1446 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1447 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1448 vm
['vim_image_id'] = image_id
1450 #create flavor at vim in case it not exist
1451 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1452 if flavor_dict
['extended']!=None:
1453 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1454 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1455 vm
['vim_flavor_id'] = flavor_id
1458 myVMDict
['imageRef'] = vm
['vim_image_id']
1459 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1460 myVMDict
['networks'] = []
1461 for iface
in vm
['interfaces']:
1463 if iface
['type']=="data":
1464 netDict
['type'] = iface
['model']
1465 elif "model" in iface
and iface
["model"]!=None:
1466 netDict
['model']=iface
['model']
1467 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1468 #discover type of interface looking at flavor
1469 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1470 for flavor_iface
in numa
.get('interfaces',[]):
1471 if flavor_iface
.get('name') == iface
['internal_name']:
1472 if flavor_iface
['dedicated'] == 'yes':
1473 netDict
['type']="PF" #passthrough
1474 elif flavor_iface
['dedicated'] == 'no':
1475 netDict
['type']="VF" #siov
1476 elif flavor_iface
['dedicated'] == 'yes:sriov':
1477 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1478 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1480 netDict
["use"]=iface
['type']
1481 if netDict
["use"]=="data" and not netDict
.get("type"):
1482 #print "netDict", netDict
1483 #print "iface", iface
1484 e_text
= "Cannot determine the interface type PF or VF of VNF '%s' VM '%s' iface '%s'" %(sce_vnf
['name'], vm
['name'], iface
['internal_name'])
1485 if flavor_dict
.get('extended')==None:
1486 raise NfvoException(e_text
+ "After database migration some information is not available. \
1487 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1489 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1490 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1491 netDict
["type"]="virtual"
1492 if "vpci" in iface
and iface
["vpci"] is not None:
1493 netDict
['vpci'] = iface
['vpci']
1494 if "mac" in iface
and iface
["mac"] is not None:
1495 netDict
['mac_address'] = iface
['mac']
1496 netDict
['name'] = iface
['internal_name']
1497 if iface
['net_id'] is None:
1498 for vnf_iface
in sce_vnf
["interfaces"]:
1501 if vnf_iface
['interface_id']==iface
['uuid']:
1502 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1505 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1506 #skip bridge ifaces not connected to any net
1507 #if 'net_id' not in netDict or netDict['net_id']==None:
1509 myVMDict
['networks'].append(netDict
)
1510 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1511 #print myVMDict['name']
1512 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1513 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1514 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1515 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1516 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1517 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1518 vm
['vim_id'] = vm_id
1519 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1520 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1521 for net
in myVMDict
['networks']:
1523 for iface
in vm
['interfaces']:
1524 if net
["name"]==iface
["internal_name"]:
1525 iface
["vim_id"]=net
["vim_id"]
1528 logger
.debug("start scenario Deployment done")
1529 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1530 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1531 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1532 return mydb
.get_instance_scenario(instance_id
)
1534 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1535 _
, message
= rollback(mydb
, vims
, rollbackList
)
1536 if isinstance(e
, db_base_Exception
):
1537 error_text
= "Exception at database"
1539 error_text
= "Exception at VIM"
1540 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1541 #logger.error("start_scenario %s", error_text)
1542 raise NfvoException(error_text
, e
.http_code
)
1544 def unify_cloud_config(cloud_config
):
1545 index_to_delete
= []
1546 users
= cloud_config
.get("users", [])
1547 for index0
in range(0,len(users
)):
1548 if index0
in index_to_delete
:
1550 for index1
in range(index0
+1,len(users
)):
1551 if index1
in index_to_delete
:
1553 if users
[index0
]["name"] == users
[index1
]["name"]:
1554 index_to_delete
.append(index1
)
1555 for key
in users
[index1
].get("key-pairs",()):
1556 if "key-pairs" not in users
[index0
]:
1557 users
[index0
]["key-pairs"] = [key
]
1558 elif key
not in users
[index0
]["key-pairs"]:
1559 users
[index0
]["key-pairs"].append(key
)
1560 index_to_delete
.sort(reverse
=True)
1561 for index
in index_to_delete
:
1564 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1565 datacenter_id
= None
1566 datacenter_name
= None
1567 if datacenter_id_name
:
1568 if utils
.check_valid_uuid(datacenter_id_name
):
1569 datacenter_id
= datacenter_id_name
1571 datacenter_name
= datacenter_id_name
1572 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1574 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1576 #print "nfvo.datacenter_action() error. Several datacenters found"
1577 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1578 return vims
.keys()[0], vims
.values()[0]
1580 def new_scenario_v03(mydb
, tenant_id
, scenario_dict
):
1581 scenario
= scenario_dict
["scenario"]
1582 if tenant_id
!= "any":
1583 check_tenant(mydb
, tenant_id
)
1584 if "tenant_id" in scenario
:
1585 if scenario
["tenant_id"] != tenant_id
:
1586 logger("Tenant '%s' not found", tenant_id
)
1587 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1588 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1592 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1593 for name
,vnf
in scenario
["vnfs"].iteritems():
1595 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1597 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1599 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1600 where
['uuid'] = vnf
['vnf_id']
1601 if 'vnf_name' in vnf
:
1602 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1603 where
['name'] = vnf
['vnf_name']
1605 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1606 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1612 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1614 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1615 vnf
['uuid']=vnf_db
[0]['uuid']
1616 vnf
['description']=vnf_db
[0]['description']
1618 # get external interfaces
1619 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1620 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1621 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1622 for ext_iface
in ext_ifaces
:
1623 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1625 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1627 #2: Insert net_key and ip_address at every vnf interface
1628 for net_name
,net
in scenario
["networks"].iteritems():
1629 net_type_bridge
=False
1631 for iface_dict
in net
["interfaces"]:
1632 logger
.debug("Iface_dict %s", iface_dict
)
1633 vnf
= iface_dict
["vnf"]
1634 iface
= iface_dict
["vnf_interface"]
1635 if vnf
not in scenario
["vnfs"]:
1636 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1637 #logger.debug(error_text)
1638 raise NfvoException(error_text
, HTTP_Not_Found
)
1639 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1640 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1641 #logger.debug(error_text)
1642 raise NfvoException(error_text
, HTTP_Bad_Request
)
1643 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1644 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1645 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1646 #logger.debug(error_text)
1647 raise NfvoException(error_text
, HTTP_Bad_Request
)
1648 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1649 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['ip_address'] = iface_dict
.get('ip_address',None)
1650 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1651 if iface_type
=='mgmt' or iface_type
=='bridge':
1652 net_type_bridge
= True
1654 net_type_data
= True
1655 if net_type_bridge
and net_type_data
:
1656 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1657 #logger.debug(error_text)
1658 raise NfvoException(error_text
, HTTP_Bad_Request
)
1659 elif net_type_bridge
:
1662 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1664 if ("implementation" in net
):
1665 if (type_
== "bridge" and net
["implementation"] == "underlay"):
1666 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at 'network':'%s'" % (net_name
)
1667 #logger.debug(error_text)
1668 raise NfvoException(error_text
, HTTP_Bad_Request
)
1669 elif (type_
<> "bridge" and net
["implementation"] == "overlay"):
1670 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at 'network':'%s'" % (net_name
)
1671 #logger.debug(error_text)
1672 raise NfvoException(error_text
, HTTP_Bad_Request
)
1673 net
.pop("implementation")
1675 if (type_
== "data" and net
["type"] == "e-line"):
1676 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type 'e-line' at 'network':'%s'" % (net_name
)
1677 #logger.debug(error_text)
1678 raise NfvoException(error_text
, HTTP_Bad_Request
)
1679 elif (type_
== "ptp" and net
["type"] == "e-lan"):
1683 net
['name'] = net_name
1684 net
['external'] = net
.get('external', False)
1686 #3: insert at database
1687 scenario
["nets"] = scenario
["networks"]
1688 scenario
['tenant_id'] = tenant_id
1689 scenario_id
= mydb
.new_scenario2(scenario
)
1693 '''Takes dict d and updates it with the values in dict u.'''
1694 '''It merges all depth levels'''
1695 for k
, v
in u
.iteritems():
1696 if isinstance(v
, collections
.Mapping
):
1697 r
= update(d
.get(k
, {}), v
)
1703 def create_instance(mydb
, tenant_id
, instance_dict
):
1704 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1705 #logger.debug("Creating instance...")
1706 scenario
= instance_dict
["scenario"]
1708 #find main datacenter
1710 datacenter2tenant
= {}
1711 datacenter
= instance_dict
.get("datacenter")
1712 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1713 myvims
[default_datacenter_id
] = vim
1714 datacenter2tenant
[default_datacenter_id
] = vim
['config']['datacenter_tenant_id']
1715 #myvim_tenant = myvim['tenant_id']
1716 # default_datacenter_name = vim['name']
1719 #print "Checking that the scenario exists and getting the scenario dictionary"
1720 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1722 #logger.debug(">>>>>>> Dictionaries before merging")
1723 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1724 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1726 scenarioDict
['datacenter_id'] = default_datacenter_id
1728 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1729 auxNetDict
['scenario'] = {}
1731 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1732 instance_name
= instance_dict
["name"]
1733 instance_description
= instance_dict
.get("description")
1735 #0 check correct parameters
1736 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1738 for scenario_net
in scenarioDict
['nets']:
1739 if net_name
== scenario_net
["name"]:
1743 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1744 if "sites" not in net_instance_desc
:
1745 net_instance_desc
["sites"] = [ {} ]
1746 site_without_datacenter_field
= False
1747 for site
in net_instance_desc
["sites"]:
1748 if site
.get("datacenter"):
1749 if site
["datacenter"] not in myvims
:
1750 #Add this datacenter to myvims
1751 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1753 datacenter2tenant
[d
] = v
['config']['datacenter_tenant_id']
1754 site
["datacenter"] = d
#change name to id
1756 if site_without_datacenter_field
:
1757 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1758 site_without_datacenter_field
= True
1759 site
["datacenter"] = default_datacenter_id
#change name to id
1761 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
1763 for scenario_vnf
in scenarioDict
['vnfs']:
1764 if vnf_name
== scenario_vnf
['name']:
1768 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
1769 if "datacenter" in vnf_instance_desc
:
1770 #Add this datacenter to myvims
1771 if vnf_instance_desc
["datacenter"] not in myvims
:
1772 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
1774 datacenter2tenant
[d
] = v
['config']['datacenter_tenant_id']
1775 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
1777 #0.1 parse cloud-config parameters
1778 cloud_config
= scenarioDict
.get("cloud-config", {})
1779 if instance_dict
.get("cloud-config"):
1780 cloud_config
.update( instance_dict
["cloud-config"])
1781 if not cloud_config
:
1784 scenarioDict
["cloud-config"] = cloud_config
1785 unify_cloud_config(cloud_config
)
1787 #0.2 merge instance information into scenario
1788 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
1789 #However, this is not possible yet.
1790 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1791 for scenario_net
in scenarioDict
['nets']:
1792 if net_name
== scenario_net
["name"]:
1793 if 'ip-profile' in net_instance_desc
:
1794 ipprofile
= net_instance_desc
['ip-profile']
1795 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
1796 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
1797 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
1798 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
1799 if 'dhcp' in ipprofile
:
1800 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
1801 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
1802 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
1803 del ipprofile
['dhcp']
1804 if 'ip_profile' not in scenario_net
:
1805 scenario_net
['ip_profile'] = ipprofile
1807 update(scenario_net
['ip_profile'],ipprofile
)
1808 for interface
in net_instance_desc
.get('interfaces', () ):
1809 if 'ip_address' in interface
:
1810 for vnf
in scenarioDict
['vnfs']:
1811 if interface
['vnf'] == vnf
['name']:
1812 for vnf_interface
in vnf
['interfaces']:
1813 if interface
['vnf_interface'] == vnf_interface
['external_name']:
1814 vnf_interface
['ip_address']=interface
['ip_address']
1816 #logger.debug(">>>>>>>> Merged dictionary")
1817 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
1820 #1. Creating new nets (sce_nets) in the VIM"
1821 for sce_net
in scenarioDict
['nets']:
1822 sce_net
["vim_id_sites"]={}
1823 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
1824 net_name
= descriptor_net
.get("vim-network-name")
1825 auxNetDict
['scenario'][sce_net
['uuid']] = {}
1827 sites
= descriptor_net
.get("sites", [ {} ])
1829 if site
.get("datacenter"):
1830 vim
= myvims
[ site
["datacenter"] ]
1831 datacenter_id
= site
["datacenter"]
1833 vim
= myvims
[ default_datacenter_id
]
1834 datacenter_id
= default_datacenter_id
1835 net_type
= sce_net
['type']
1836 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
1837 if sce_net
["external"]:
1839 net_name
= sce_net
["name"]
1840 if "netmap-use" in site
or "netmap-create" in site
:
1841 create_network
= False
1842 lookfor_network
= False
1843 if "netmap-use" in site
:
1844 lookfor_network
= True
1845 if utils
.check_valid_uuid(site
["netmap-use"]):
1846 filter_text
= "scenario id '%s'" % site
["netmap-use"]
1847 lookfor_filter
["id"] = site
["netmap-use"]
1849 filter_text
= "scenario name '%s'" % site
["netmap-use"]
1850 lookfor_filter
["name"] = site
["netmap-use"]
1851 if "netmap-create" in site
:
1852 create_network
= True
1853 net_vim_name
= net_name
1854 if site
["netmap-create"]:
1855 net_vim_name
= site
["netmap-create"]
1857 elif sce_net
['vim_id'] != None:
1858 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
1859 create_network
= False
1860 lookfor_network
= True
1861 lookfor_filter
["id"] = sce_net
['vim_id']
1862 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
1863 #look for network at datacenter and return error
1865 #There is not a netmap, look at datacenter for a net with this name and create if not found
1866 create_network
= True
1867 lookfor_network
= True
1868 lookfor_filter
["name"] = sce_net
["name"]
1869 net_vim_name
= sce_net
["name"]
1870 filter_text
= "scenario name '%s'" % sce_net
["name"]
1873 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
1874 net_name
= net_name
[:255] #limit length
1875 net_vim_name
= net_name
1876 create_network
= True
1877 lookfor_network
= False
1880 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
1881 if len(vim_nets
) > 1:
1882 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1883 elif len(vim_nets
) == 0:
1884 if not create_network
:
1885 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1887 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
1888 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
1889 create_network
= False
1891 #if network is not external
1892 network_id
= vim
.new_network(net_vim_name
, net_type
, sce_net
.get('ip_profile',None))
1893 sce_net
["vim_id_sites"][datacenter_id
] = network_id
1894 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = network_id
1895 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':network_id
})
1896 sce_net
["created"] = True
1898 #2. Creating new nets (vnf internal nets) in the VIM"
1899 #For each vnf net, we create it and we add it to instanceNetlist.
1900 for sce_vnf
in scenarioDict
['vnfs']:
1901 for net
in sce_vnf
['nets']:
1902 if sce_vnf
.get("datacenter"):
1903 vim
= myvims
[ sce_vnf
["datacenter"] ]
1904 datacenter_id
= sce_vnf
["datacenter"]
1906 vim
= myvims
[ default_datacenter_id
]
1907 datacenter_id
= default_datacenter_id
1908 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
1909 net_name
= descriptor_net
.get("name")
1911 net_name
= "%s.%s" %(instance_name
, net
["name"])
1912 net_name
= net_name
[:255] #limit length
1913 net_type
= net
['type']
1914 network_id
= vim
.new_network(net_name
, net_type
, net
.get('ip_profile',None))
1915 net
['vim_id'] = network_id
1916 if sce_vnf
['uuid'] not in auxNetDict
:
1917 auxNetDict
[sce_vnf
['uuid']] = {}
1918 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1919 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1920 net
["created"] = True
1923 #print "auxNetDict:"
1924 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1926 #3. Creating new vm instances in the VIM
1927 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1928 for sce_vnf
in scenarioDict
['vnfs']:
1929 if sce_vnf
.get("datacenter"):
1930 vim
= myvims
[ sce_vnf
["datacenter"] ]
1931 datacenter_id
= sce_vnf
["datacenter"]
1933 vim
= myvims
[ default_datacenter_id
]
1934 datacenter_id
= default_datacenter_id
1935 sce_vnf
["datacenter_id"] = datacenter_id
1937 for vm
in sce_vnf
['vms']:
1940 myVMDict
['name'] = "{}.{}.{}".format(instance_name
,sce_vnf
['name'],chr(96+i
))
1941 myVMDict
['description'] = myVMDict
['name'][0:99]
1943 # myVMDict['start'] = "no"
1944 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1945 #create image at vim in case it not exist
1946 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1947 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
1948 vm
['vim_image_id'] = image_id
1950 #create flavor at vim in case it not exist
1951 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1952 if flavor_dict
['extended']!=None:
1953 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1954 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
1959 #Obtain information for additional disks
1960 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
1961 if not extended_flavor_dict
:
1962 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
1965 #extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
1966 myVMDict
['disks'] = None
1967 extended_info
= extended_flavor_dict
[0]['extended']
1968 if extended_info
!= None:
1969 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
1970 if 'disks' in extended_flavor_dict_yaml
:
1971 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
1976 vm
['vim_flavor_id'] = flavor_id
1978 myVMDict
['imageRef'] = vm
['vim_image_id']
1979 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1980 myVMDict
['networks'] = []
1981 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
1982 for iface
in vm
['interfaces']:
1984 if iface
['type']=="data":
1985 netDict
['type'] = iface
['model']
1986 elif "model" in iface
and iface
["model"]!=None:
1987 netDict
['model']=iface
['model']
1988 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1989 #discover type of interface looking at flavor
1990 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1991 for flavor_iface
in numa
.get('interfaces',[]):
1992 if flavor_iface
.get('name') == iface
['internal_name']:
1993 if flavor_iface
['dedicated'] == 'yes':
1994 netDict
['type']="PF" #passthrough
1995 elif flavor_iface
['dedicated'] == 'no':
1996 netDict
['type']="VF" #siov
1997 elif flavor_iface
['dedicated'] == 'yes:sriov':
1998 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1999 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2001 netDict
["use"]=iface
['type']
2002 if netDict
["use"]=="data" and not netDict
.get("type"):
2003 #print "netDict", netDict
2004 #print "iface", iface
2005 e_text
= "Cannot determine the interface type PF or VF of VNF '%s' VM '%s' iface '%s'" %(sce_vnf
['name'], vm
['name'], iface
['internal_name'])
2006 if flavor_dict
.get('extended')==None:
2007 raise NfvoException(e_text
+ "After database migration some information is not available. \
2008 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2010 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2011 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2012 netDict
["type"]="virtual"
2013 if "vpci" in iface
and iface
["vpci"] is not None:
2014 netDict
['vpci'] = iface
['vpci']
2015 if "mac" in iface
and iface
["mac"] is not None:
2016 netDict
['mac_address'] = iface
['mac']
2017 netDict
['name'] = iface
['internal_name']
2018 if iface
['net_id'] is None:
2019 for vnf_iface
in sce_vnf
["interfaces"]:
2022 if vnf_iface
['interface_id']==iface
['uuid']:
2023 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
2026 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2027 #skip bridge ifaces not connected to any net
2028 #if 'net_id' not in netDict or netDict['net_id']==None:
2030 myVMDict
['networks'].append(netDict
)
2031 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2032 #print myVMDict['name']
2033 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2034 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2035 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2036 vm_id
= vim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
2037 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'], cloud_config
= cloud_config
,
2038 disk_list
= myVMDict
['disks'])
2040 vm
['vim_id'] = vm_id
2041 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2042 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2043 for net
in myVMDict
['networks']:
2045 for iface
in vm
['interfaces']:
2046 if net
["name"]==iface
["internal_name"]:
2047 iface
["vim_id"]=net
["vim_id"]
2049 scenarioDict
["datacenter2tenant"] = datacenter2tenant
2050 logger
.debug("create_instance Deployment done scenarioDict: %s",
2051 yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False) )
2052 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
2053 return mydb
.get_instance_scenario(instance_id
)
2054 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2055 message
= rollback(mydb
, myvims
, rollbackList
)
2056 if isinstance(e
, db_base_Exception
):
2057 error_text
= "database Exception"
2058 elif isinstance(e
, vimconn
.vimconnException
):
2059 error_text
= "VIM Exception"
2061 error_text
= "Exception"
2062 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2063 #logger.error("create_instance: %s", error_text)
2064 raise NfvoException(error_text
, e
.http_code
)
2066 def delete_instance(mydb
, tenant_id
, instance_id
):
2067 #print "Checking that the instance_id exists and getting the instance dictionary"
2068 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2069 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2070 tenant_id
= instanceDict
["tenant_id"]
2071 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2073 #1. Delete from Database
2074 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2082 for sce_vnf
in instanceDict
['vnfs']:
2083 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2084 if datacenter_key
not in myvims
:
2085 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2086 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2088 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2089 sce_vnf
["datacenter_tenant_id"]))
2090 myvims
[datacenter_key
] = None
2092 myvims
[datacenter_key
] = vims
.values()[0]
2093 myvim
= myvims
[datacenter_key
]
2094 for vm
in sce_vnf
['vms']:
2096 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2099 myvim
.delete_vminstance(vm
['vim_vm_id'])
2100 except vimconn
.vimconnNotFoundException
as e
:
2101 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2102 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2103 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2104 except vimconn
.vimconnException
as e
:
2105 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2106 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2107 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2111 for net
in instanceDict
['nets']:
2112 if not net
['created']:
2113 continue #skip not created nets
2114 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2115 if datacenter_key
not in myvims
:
2116 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2117 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2119 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2120 myvims
[datacenter_key
] = None
2122 myvims
[datacenter_key
] = vims
.values()[0]
2123 myvim
= myvims
[datacenter_key
]
2126 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2129 myvim
.delete_network(net
['vim_net_id'])
2130 except vimconn
.vimconnNotFoundException
as e
:
2131 error_msg
+="\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2132 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2133 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2134 except vimconn
.vimconnException
as e
:
2135 error_msg
+="\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'], net
["datacenter_id"], e
.http_code
, str(e
))
2136 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2137 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2138 if len(error_msg
)>0:
2139 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2141 return 'instance ' + message
+ ' deleted'
2143 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2144 '''Refreshes a scenario instance. It modifies instanceDict'''
2146 - result: <0 if there is any unexpected error, n>=0 if no errors where n is the number of vms and nets that couldn't be updated in the database
2149 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2150 #print "nfvo.refresh_instance begins"
2151 #print json.dumps(instanceDict, indent=4)
2153 #print "Getting the VIM URL and the VIM tenant_id"
2156 # 1. Getting VIM vm and net list
2157 vms_updated
= [] #List of VM instance uuids in openmano that were updated
2160 for sce_vnf
in instanceDict
['vnfs']:
2161 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2162 if datacenter_key
not in vm_list
:
2163 vm_list
[datacenter_key
] = []
2164 if datacenter_key
not in myvims
:
2165 vims
= get_vim(mydb
, nfvo_tenant
, datacenter_id
=sce_vnf
["datacenter_id"],
2166 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2168 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"]))
2169 myvims
[datacenter_key
] = None
2171 myvims
[datacenter_key
] = vims
.values()[0]
2172 for vm
in sce_vnf
['vms']:
2173 vm_list
[datacenter_key
].append(vm
['vim_vm_id'])
2174 vms_notupdated
.append(vm
["uuid"])
2176 nets_updated
= [] #List of VM instance uuids in openmano that were updated
2179 for net
in instanceDict
['nets']:
2180 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2181 if datacenter_key
not in net_list
:
2182 net_list
[datacenter_key
] = []
2183 if datacenter_key
not in myvims
:
2184 vims
= get_vim(mydb
, nfvo_tenant
, datacenter_id
=net
["datacenter_id"],
2185 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2187 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2188 myvims
[datacenter_key
] = None
2190 myvims
[datacenter_key
] = vims
.values()[0]
2192 net_list
[datacenter_key
].append(net
['vim_net_id'])
2193 nets_notupdated
.append(net
["uuid"])
2195 # 1. Getting the status of all VMs
2197 for datacenter_key
in myvims
:
2198 if not vm_list
.get(datacenter_key
):
2202 if not myvims
[datacenter_key
]:
2203 failed_message
= "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"])
2206 vm_dict
.update(myvims
[datacenter_key
].refresh_vms_status(vm_list
[datacenter_key
]) )
2208 except vimconn
.vimconnException
as e
:
2209 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
2210 failed_message
= str(e
)
2212 for vm
in vm_list
[datacenter_key
]:
2213 vm_dict
[vm
] = {'status': "VIM_ERROR", 'error_msg': failed_message
}
2215 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2216 for sce_vnf
in instanceDict
['vnfs']:
2217 for vm
in sce_vnf
['vms']:
2218 vm_id
= vm
['vim_vm_id']
2219 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
2220 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2221 has_mgmt_iface
= False
2222 for iface
in vm
["interfaces"]:
2223 if iface
["type"]=="mgmt":
2224 has_mgmt_iface
= True
2225 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
2226 vm_dict
[vm_id
]['status'] = "ACTIVE"
2227 if vm_dict
[vm_id
].get('error_msg') and len(vm_dict
[vm_id
]['error_msg']) >= 1024:
2228 vm_dict
[vm_id
]['error_msg'] = vm_dict
[vm_id
]['error_msg'][:516] + " ... " + vm_dict
[vm_id
]['error_msg'][-500:]
2229 if vm
['status'] != vm_dict
[vm_id
]['status'] or vm
.get('error_msg')!=vm_dict
[vm_id
].get('error_msg') or vm
.get('vim_info')!=vm_dict
[vm_id
].get('vim_info'):
2230 vm
['status'] = vm_dict
[vm_id
]['status']
2231 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
2232 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
2233 # 2.1. Update in openmano DB the VMs whose status changed
2235 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
2236 vms_notupdated
.remove(vm
["uuid"])
2238 vms_updated
.append(vm
["uuid"])
2239 except db_base_Exception
as e
:
2240 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2241 # 2.2. Update in openmano DB the interface VMs
2242 for interface
in interfaces
:
2243 #translate from vim_net_id to instance_net_id
2245 for net
in instanceDict
['nets']:
2246 if net
["vim_net_id"] == interface
["vim_net_id"]:
2247 network_id_list
.append(net
["uuid"])
2248 if not network_id_list
:
2250 del interface
["vim_net_id"]
2252 for network_id
in network_id_list
:
2253 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
2254 except db_base_Exception
as e
:
2255 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
2257 # 3. Getting the status of all nets
2259 for datacenter_key
in myvims
:
2260 if not net_list
.get(datacenter_key
):
2264 if not myvims
[datacenter_key
]:
2265 failed_message
= "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"])
2268 net_dict
.update(myvims
[datacenter_key
].refresh_nets_status(net_list
[datacenter_key
]) )
2270 except vimconn
.vimconnException
as e
:
2271 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
2272 failed_message
= str(e
)
2274 for net
in net_list
[datacenter_key
]:
2275 net_dict
[net
] = {'status': "VIM_ERROR", 'error_msg': failed_message
}
2277 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2278 # TODO: update nets inside a vnf
2279 for net
in instanceDict
['nets']:
2280 net_id
= net
['vim_net_id']
2281 if net_dict
[net_id
].get('error_msg') and len(net_dict
[net_id
]['error_msg']) >= 1024:
2282 net_dict
[net_id
]['error_msg'] = net_dict
[net_id
]['error_msg'][:516] + " ... " + net_dict
[vm_id
]['error_msg'][-500:]
2283 if net
['status'] != net_dict
[net_id
]['status'] or net
.get('error_msg')!=net_dict
[net_id
].get('error_msg') or net
.get('vim_info')!=net_dict
[net_id
].get('vim_info'):
2284 net
['status'] = net_dict
[net_id
]['status']
2285 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
2286 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
2287 # 5.1. Update in openmano DB the nets whose status changed
2289 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
2290 nets_notupdated
.remove(net
["uuid"])
2292 nets_updated
.append(net
["uuid"])
2293 except db_base_Exception
as e
:
2294 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2296 # Returns appropriate output
2297 #print "nfvo.refresh_instance finishes"
2298 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2299 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
2300 instance_id
= instanceDict
['uuid']
2301 if len(vms_notupdated
)+len(nets_notupdated
)>0:
2302 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
2303 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
2305 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2307 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2308 #print "Checking that the instance_id exists and getting the instance dictionary"
2309 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2310 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2312 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2313 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2315 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2316 myvim
= vims
.values()[0]
2319 input_vnfs
= action_dict
.pop("vnfs", [])
2320 input_vms
= action_dict
.pop("vms", [])
2321 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2325 for sce_vnf
in instanceDict
['vnfs']:
2326 for vm
in sce_vnf
['vms']:
2327 if not action_over_all
:
2328 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2329 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2332 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2333 if "console" in action_dict
:
2334 if not global_config
["http_console_proxy"]:
2335 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2336 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2337 protocol
=data
["protocol"],
2338 ip
= data
["server"],
2339 port
= data
["port"],
2340 suffix
= data
["suffix"]),
2344 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2345 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2346 "description": "this console is only reachable by local interface",
2351 #print "console data", data
2353 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2354 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2355 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2356 protocol
=data
["protocol"],
2357 ip
= global_config
["http_console_host"],
2358 port
= console_thread
.port
,
2359 suffix
= data
["suffix"]),
2363 except NfvoException
as e
:
2364 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2368 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2370 except vimconn
.vimconnException
as e
:
2371 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2374 if vm_ok
==0: #all goes wrong
2379 def create_or_use_console_proxy_thread(console_server
, console_port
):
2380 #look for a non-used port
2381 console_thread_key
= console_server
+ ":" + str(console_port
)
2382 if console_thread_key
in global_config
["console_thread"]:
2383 #global_config["console_thread"][console_thread_key].start_timeout()
2384 return global_config
["console_thread"][console_thread_key
]
2386 for port
in global_config
["console_port_iterator"]():
2387 #print "create_or_use_console_proxy_thread() port:", port
2388 if port
in global_config
["console_ports"]:
2391 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2393 global_config
["console_thread"][console_thread_key
] = clithread
2394 global_config
["console_ports"][port
] = console_thread_key
2396 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2397 #port used, try with onoher
2399 except cli
.ConsoleProxyException
as e
:
2400 raise NfvoException(str(e
), HTTP_Bad_Request
)
2401 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2403 def check_tenant(mydb
, tenant_id
):
2404 '''check that tenant exists at database'''
2405 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2407 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2410 def new_tenant(mydb
, tenant_dict
):
2411 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2414 def delete_tenant(mydb
, tenant
):
2415 #get nfvo_tenant info
2417 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2418 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2419 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2421 def new_datacenter(mydb
, datacenter_descriptor
):
2422 if "config" in datacenter_descriptor
:
2423 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2424 #Check that datacenter-type is correct
2425 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2428 module
= "vimconn_" + datacenter_type
2429 module_info
= imp
.find_module(module
)
2430 except (IOError, ImportError):
2431 if module_info
and module_info
[0]:
2432 file.close(module_info
[0])
2433 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2435 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2436 return datacenter_id
2438 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2439 #obtain data, check that only one exist
2440 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2442 datacenter_id
= datacenter
['uuid']
2443 where
={'uuid': datacenter
['uuid']}
2444 if "config" in datacenter_descriptor
:
2445 if datacenter_descriptor
['config']!=None:
2447 new_config_dict
= datacenter_descriptor
["config"]
2450 for k
in new_config_dict
:
2451 if new_config_dict
[k
]==None:
2454 config_dict
= yaml
.load(datacenter
["config"])
2455 config_dict
.update(new_config_dict
)
2459 except Exception as e
:
2460 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2461 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2462 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2463 return datacenter_id
2465 def delete_datacenter(mydb
, datacenter
):
2466 #get nfvo_tenant info
2467 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2468 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2469 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2471 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
2472 #get datacenter info
2473 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2474 datacenter_name
=myvim
["name"]
2476 create_vim_tenant
=True if vim_tenant_id
==None and vim_tenant_name
==None else False
2478 #get nfvo_tenant info
2479 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2480 if vim_tenant_name
==None:
2481 vim_tenant_name
=tenant_dict
['name']
2483 #check that this association does not exist before
2484 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2485 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2486 if len(tenants_datacenters
)>0:
2487 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2489 vim_tenant_id_exist_atdb
=False
2490 if not create_vim_tenant
:
2491 where_
={"datacenter_id": datacenter_id
}
2492 if vim_tenant_id
!=None:
2493 where_
["vim_tenant_id"] = vim_tenant_id
2494 if vim_tenant_name
!=None:
2495 where_
["vim_tenant_name"] = vim_tenant_name
2496 #check if vim_tenant_id is already at database
2497 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2498 if len(datacenter_tenants_dict
)>=1:
2499 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2500 vim_tenant_id_exist_atdb
=True
2501 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2503 datacenter_tenants_dict
= {}
2504 #insert at table datacenter_tenants
2505 else: #if vim_tenant_id==None:
2506 #create tenant at VIM if not provided
2508 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2509 except vimconn
.vimconnException
as e
:
2510 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2511 datacenter_tenants_dict
= {}
2512 datacenter_tenants_dict
["created"]="true"
2514 #fill datacenter_tenants table
2515 if not vim_tenant_id_exist_atdb
:
2516 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2517 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2518 datacenter_tenants_dict
["user"] = vim_username
2519 datacenter_tenants_dict
["passwd"] = vim_password
2520 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2522 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
2523 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2524 datacenter_tenants_dict
["uuid"] = id_
2526 #fill tenants_datacenters table
2527 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2528 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2529 return datacenter_id
2531 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2532 #get datacenter info
2533 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2535 #get nfvo_tenant info
2536 if not tenant_id
or tenant_id
=="any":
2539 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2540 tenant_uuid
= tenant_dict
['uuid']
2542 #check that this association exist before
2543 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2545 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2546 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2547 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2548 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2550 #delete this association
2551 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2553 #get vim_tenant info and deletes
2555 for tenant_datacenter_item
in tenant_datacenter_list
:
2556 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2557 #try to delete vim:tenant
2559 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2560 if vim_tenant_dict
['created']=='true':
2561 #delete tenant at VIM if created by NFVO
2563 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2564 except vimconn
.vimconnException
as e
:
2565 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2566 logger
.warn(warning
)
2567 except db_base_Exception
as e
:
2568 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2569 pass #the error will be caused because dependencies, vim_tenant can not be deleted
2571 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2573 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2575 #get datacenter info
2576 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2578 if 'net-update' in action_dict
:
2580 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2582 except vimconn
.vimconnException
as e
:
2583 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2584 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2585 #update nets Change from VIM format to NFVO format
2588 net_nfvo
={'datacenter_id': datacenter_id
}
2589 net_nfvo
['name'] = net
['name']
2590 #net_nfvo['description']= net['name']
2591 net_nfvo
['vim_net_id'] = net
['id']
2592 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2593 net_nfvo
['shared'] = net
['shared']
2594 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2595 net_list
.append(net_nfvo
)
2596 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2597 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2599 elif 'net-edit' in action_dict
:
2600 net
= action_dict
['net-edit'].pop('net')
2601 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2602 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2603 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2605 elif 'net-delete' in action_dict
:
2606 net
= action_dict
['net-deelte'].get('net')
2607 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2608 result
= mydb
.delete_row(FROM
='datacenter_nets',
2609 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2613 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2615 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2616 #get datacenter info
2617 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2619 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2620 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2621 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2624 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2625 #get datacenter info
2626 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2629 action_dict
= action_dict
["netmap"]
2630 if 'vim_id' in action_dict
:
2631 filter_dict
["id"] = action_dict
['vim_id']
2632 if 'vim_name' in action_dict
:
2633 filter_dict
["name"] = action_dict
['vim_name']
2635 filter_dict
["shared"] = True
2638 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
2639 except vimconn
.vimconnException
as e
:
2640 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
2641 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2642 if len(vim_nets
)>1 and action_dict
:
2643 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
2644 elif len(vim_nets
)==0: # and action_dict:
2645 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
2647 for net
in vim_nets
:
2648 net_nfvo
={'datacenter_id': datacenter_id
}
2649 if action_dict
and "name" in action_dict
:
2650 net_nfvo
['name'] = action_dict
['name']
2652 net_nfvo
['name'] = net
['name']
2653 #net_nfvo['description']= net['name']
2654 net_nfvo
['vim_net_id'] = net
['id']
2655 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2656 net_nfvo
['shared'] = net
['shared']
2657 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2659 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2660 net_nfvo
["status"] = "OK"
2661 net_nfvo
["uuid"] = net_id
2662 except db_base_Exception
as e
:
2666 net_nfvo
["status"] = "FAIL: " + str(e
)
2667 net_list
.append(net_nfvo
)
2670 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2671 #get datacenter info
2672 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2675 if utils
.check_valid_uuid(name
):
2676 filter_dict
["id"] = name
2678 filter_dict
["name"] = name
2680 if item
=="networks":
2681 #filter_dict['tenant_id'] = myvim['tenant_id']
2682 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2683 elif item
=="tenants":
2684 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2686 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2687 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
2688 if name
and len(content
)==1:
2689 return {item
[:-1]: content
[0]}
2690 elif name
and len(content
)==0:
2691 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
2694 return {item
: content
}
2695 except vimconn
.vimconnException
as e
:
2696 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
2697 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
2699 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
2700 #get datacenter info
2701 if tenant_id
== "any":
2704 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2706 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2707 logger
.debug("vim_action_delete vim response: " + str(content
))
2708 items
= content
.values()[0]
2709 if type(items
)==list and len(items
)==0:
2710 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
2711 elif type(items
)==list and len(items
)>1:
2712 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
2713 else: # it is a dict
2714 item_id
= items
["id"]
2715 item_name
= str(items
.get("name"))
2718 if item
=="networks":
2719 content
= myvim
.delete_network(item_id
)
2720 elif item
=="tenants":
2721 content
= myvim
.delete_tenant(item_id
)
2723 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2724 except vimconn
.vimconnException
as e
:
2725 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
2726 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
2728 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
2730 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2731 #get datacenter info
2732 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
2733 if tenant_id
== "any":
2735 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2737 if item
=="networks":
2738 net
= descriptor
["network"]
2739 net_name
= net
.pop("name")
2740 net_type
= net
.pop("type", "bridge")
2741 net_public
= net
.pop("shared", False)
2742 net_ipprofile
= net
.pop("ip_profile", None)
2743 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, **net
)
2744 elif item
=="tenants":
2745 tenant
= descriptor
["tenant"]
2746 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2748 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2749 except vimconn
.vimconnException
as e
:
2750 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
2752 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)