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 if "port-security" in iface
and iface
["port-security"] is not None:
1497 netDict
['port_security'] = iface
['port-security']
1498 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
1499 netDict
['floating_ip'] = iface
['floating-ip']
1500 netDict
['name'] = iface
['internal_name']
1501 if iface
['net_id'] is None:
1502 for vnf_iface
in sce_vnf
["interfaces"]:
1505 if vnf_iface
['interface_id']==iface
['uuid']:
1506 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1509 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1510 #skip bridge ifaces not connected to any net
1511 #if 'net_id' not in netDict or netDict['net_id']==None:
1513 myVMDict
['networks'].append(netDict
)
1514 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1515 #print myVMDict['name']
1516 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1517 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1518 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1519 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1520 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1521 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1522 vm
['vim_id'] = vm_id
1523 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1524 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1525 for net
in myVMDict
['networks']:
1527 for iface
in vm
['interfaces']:
1528 if net
["name"]==iface
["internal_name"]:
1529 iface
["vim_id"]=net
["vim_id"]
1532 logger
.debug("start scenario Deployment done")
1533 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1534 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1535 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1536 return mydb
.get_instance_scenario(instance_id
)
1538 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1539 _
, message
= rollback(mydb
, vims
, rollbackList
)
1540 if isinstance(e
, db_base_Exception
):
1541 error_text
= "Exception at database"
1543 error_text
= "Exception at VIM"
1544 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1545 #logger.error("start_scenario %s", error_text)
1546 raise NfvoException(error_text
, e
.http_code
)
1548 def unify_cloud_config(cloud_config
):
1549 index_to_delete
= []
1550 users
= cloud_config
.get("users", [])
1551 for index0
in range(0,len(users
)):
1552 if index0
in index_to_delete
:
1554 for index1
in range(index0
+1,len(users
)):
1555 if index1
in index_to_delete
:
1557 if users
[index0
]["name"] == users
[index1
]["name"]:
1558 index_to_delete
.append(index1
)
1559 for key
in users
[index1
].get("key-pairs",()):
1560 if "key-pairs" not in users
[index0
]:
1561 users
[index0
]["key-pairs"] = [key
]
1562 elif key
not in users
[index0
]["key-pairs"]:
1563 users
[index0
]["key-pairs"].append(key
)
1564 index_to_delete
.sort(reverse
=True)
1565 for index
in index_to_delete
:
1568 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1569 datacenter_id
= None
1570 datacenter_name
= None
1571 if datacenter_id_name
:
1572 if utils
.check_valid_uuid(datacenter_id_name
):
1573 datacenter_id
= datacenter_id_name
1575 datacenter_name
= datacenter_id_name
1576 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1578 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1580 #print "nfvo.datacenter_action() error. Several datacenters found"
1581 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1582 return vims
.keys()[0], vims
.values()[0]
1584 def new_scenario_v03(mydb
, tenant_id
, scenario_dict
):
1585 scenario
= scenario_dict
["scenario"]
1586 if tenant_id
!= "any":
1587 check_tenant(mydb
, tenant_id
)
1588 if "tenant_id" in scenario
:
1589 if scenario
["tenant_id"] != tenant_id
:
1590 logger("Tenant '%s' not found", tenant_id
)
1591 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1592 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1596 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1597 for name
,vnf
in scenario
["vnfs"].iteritems():
1599 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1601 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1603 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1604 where
['uuid'] = vnf
['vnf_id']
1605 if 'vnf_name' in vnf
:
1606 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1607 where
['name'] = vnf
['vnf_name']
1609 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1610 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1616 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1618 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1619 vnf
['uuid']=vnf_db
[0]['uuid']
1620 vnf
['description']=vnf_db
[0]['description']
1622 # get external interfaces
1623 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1624 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1625 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1626 for ext_iface
in ext_ifaces
:
1627 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1629 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1631 #2: Insert net_key and ip_address at every vnf interface
1632 for net_name
,net
in scenario
["networks"].iteritems():
1633 net_type_bridge
=False
1635 for iface_dict
in net
["interfaces"]:
1636 logger
.debug("Iface_dict %s", iface_dict
)
1637 vnf
= iface_dict
["vnf"]
1638 iface
= iface_dict
["vnf_interface"]
1639 if vnf
not in scenario
["vnfs"]:
1640 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1641 #logger.debug(error_text)
1642 raise NfvoException(error_text
, HTTP_Not_Found
)
1643 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1644 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1645 #logger.debug(error_text)
1646 raise NfvoException(error_text
, HTTP_Bad_Request
)
1647 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1648 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1649 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1650 #logger.debug(error_text)
1651 raise NfvoException(error_text
, HTTP_Bad_Request
)
1652 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1653 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['ip_address'] = iface_dict
.get('ip_address',None)
1654 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1655 if iface_type
=='mgmt' or iface_type
=='bridge':
1656 net_type_bridge
= True
1658 net_type_data
= True
1659 if net_type_bridge
and net_type_data
:
1660 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1661 #logger.debug(error_text)
1662 raise NfvoException(error_text
, HTTP_Bad_Request
)
1663 elif net_type_bridge
:
1666 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1668 if ("implementation" in net
):
1669 if (type_
== "bridge" and net
["implementation"] == "underlay"):
1670 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at 'network':'%s'" % (net_name
)
1671 #logger.debug(error_text)
1672 raise NfvoException(error_text
, HTTP_Bad_Request
)
1673 elif (type_
<> "bridge" and net
["implementation"] == "overlay"):
1674 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at 'network':'%s'" % (net_name
)
1675 #logger.debug(error_text)
1676 raise NfvoException(error_text
, HTTP_Bad_Request
)
1677 net
.pop("implementation")
1679 if (type_
== "data" and net
["type"] == "e-line"):
1680 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type 'e-line' at 'network':'%s'" % (net_name
)
1681 #logger.debug(error_text)
1682 raise NfvoException(error_text
, HTTP_Bad_Request
)
1683 elif (type_
== "ptp" and net
["type"] == "e-lan"):
1687 net
['name'] = net_name
1688 net
['external'] = net
.get('external', False)
1690 #3: insert at database
1691 scenario
["nets"] = scenario
["networks"]
1692 scenario
['tenant_id'] = tenant_id
1693 scenario_id
= mydb
.new_scenario2(scenario
)
1697 '''Takes dict d and updates it with the values in dict u.'''
1698 '''It merges all depth levels'''
1699 for k
, v
in u
.iteritems():
1700 if isinstance(v
, collections
.Mapping
):
1701 r
= update(d
.get(k
, {}), v
)
1707 def create_instance(mydb
, tenant_id
, instance_dict
):
1708 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1709 #logger.debug("Creating instance...")
1710 scenario
= instance_dict
["scenario"]
1712 #find main datacenter
1714 datacenter2tenant
= {}
1715 datacenter
= instance_dict
.get("datacenter")
1716 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1717 myvims
[default_datacenter_id
] = vim
1718 datacenter2tenant
[default_datacenter_id
] = vim
['config']['datacenter_tenant_id']
1719 #myvim_tenant = myvim['tenant_id']
1720 # default_datacenter_name = vim['name']
1723 #print "Checking that the scenario exists and getting the scenario dictionary"
1724 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1726 #logger.debug(">>>>>>> Dictionaries before merging")
1727 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1728 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1730 scenarioDict
['datacenter_id'] = default_datacenter_id
1732 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1733 auxNetDict
['scenario'] = {}
1735 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1736 instance_name
= instance_dict
["name"]
1737 instance_description
= instance_dict
.get("description")
1739 #0 check correct parameters
1740 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1742 for scenario_net
in scenarioDict
['nets']:
1743 if net_name
== scenario_net
["name"]:
1747 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1748 if "sites" not in net_instance_desc
:
1749 net_instance_desc
["sites"] = [ {} ]
1750 site_without_datacenter_field
= False
1751 for site
in net_instance_desc
["sites"]:
1752 if site
.get("datacenter"):
1753 if site
["datacenter"] not in myvims
:
1754 #Add this datacenter to myvims
1755 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1757 datacenter2tenant
[d
] = v
['config']['datacenter_tenant_id']
1758 site
["datacenter"] = d
#change name to id
1760 if site_without_datacenter_field
:
1761 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1762 site_without_datacenter_field
= True
1763 site
["datacenter"] = default_datacenter_id
#change name to id
1765 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
1767 for scenario_vnf
in scenarioDict
['vnfs']:
1768 if vnf_name
== scenario_vnf
['name']:
1772 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
1773 if "datacenter" in vnf_instance_desc
:
1774 #Add this datacenter to myvims
1775 if vnf_instance_desc
["datacenter"] not in myvims
:
1776 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
1778 datacenter2tenant
[d
] = v
['config']['datacenter_tenant_id']
1779 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
1781 #0.1 parse cloud-config parameters
1782 cloud_config
= scenarioDict
.get("cloud-config", {})
1783 if instance_dict
.get("cloud-config"):
1784 cloud_config
.update( instance_dict
["cloud-config"])
1785 if not cloud_config
:
1788 scenarioDict
["cloud-config"] = cloud_config
1789 unify_cloud_config(cloud_config
)
1791 #0.2 merge instance information into scenario
1792 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
1793 #However, this is not possible yet.
1794 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1795 for scenario_net
in scenarioDict
['nets']:
1796 if net_name
== scenario_net
["name"]:
1797 if 'ip-profile' in net_instance_desc
:
1798 ipprofile
= net_instance_desc
['ip-profile']
1799 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
1800 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
1801 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
1802 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
1803 if 'dhcp' in ipprofile
:
1804 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
1805 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
1806 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
1807 del ipprofile
['dhcp']
1808 if 'ip_profile' not in scenario_net
:
1809 scenario_net
['ip_profile'] = ipprofile
1811 update(scenario_net
['ip_profile'],ipprofile
)
1812 for interface
in net_instance_desc
.get('interfaces', () ):
1813 if 'ip_address' in interface
:
1814 for vnf
in scenarioDict
['vnfs']:
1815 if interface
['vnf'] == vnf
['name']:
1816 for vnf_interface
in vnf
['interfaces']:
1817 if interface
['vnf_interface'] == vnf_interface
['external_name']:
1818 vnf_interface
['ip_address']=interface
['ip_address']
1820 #logger.debug(">>>>>>>> Merged dictionary")
1821 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
1824 #1. Creating new nets (sce_nets) in the VIM"
1825 for sce_net
in scenarioDict
['nets']:
1826 sce_net
["vim_id_sites"]={}
1827 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
1828 net_name
= descriptor_net
.get("vim-network-name")
1829 auxNetDict
['scenario'][sce_net
['uuid']] = {}
1831 sites
= descriptor_net
.get("sites", [ {} ])
1833 if site
.get("datacenter"):
1834 vim
= myvims
[ site
["datacenter"] ]
1835 datacenter_id
= site
["datacenter"]
1837 vim
= myvims
[ default_datacenter_id
]
1838 datacenter_id
= default_datacenter_id
1839 net_type
= sce_net
['type']
1840 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
1841 if sce_net
["external"]:
1843 net_name
= sce_net
["name"]
1844 if "netmap-use" in site
or "netmap-create" in site
:
1845 create_network
= False
1846 lookfor_network
= False
1847 if "netmap-use" in site
:
1848 lookfor_network
= True
1849 if utils
.check_valid_uuid(site
["netmap-use"]):
1850 filter_text
= "scenario id '%s'" % site
["netmap-use"]
1851 lookfor_filter
["id"] = site
["netmap-use"]
1853 filter_text
= "scenario name '%s'" % site
["netmap-use"]
1854 lookfor_filter
["name"] = site
["netmap-use"]
1855 if "netmap-create" in site
:
1856 create_network
= True
1857 net_vim_name
= net_name
1858 if site
["netmap-create"]:
1859 net_vim_name
= site
["netmap-create"]
1861 elif sce_net
['vim_id'] != None:
1862 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
1863 create_network
= False
1864 lookfor_network
= True
1865 lookfor_filter
["id"] = sce_net
['vim_id']
1866 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
1867 #look for network at datacenter and return error
1869 #There is not a netmap, look at datacenter for a net with this name and create if not found
1870 create_network
= True
1871 lookfor_network
= True
1872 lookfor_filter
["name"] = sce_net
["name"]
1873 net_vim_name
= sce_net
["name"]
1874 filter_text
= "scenario name '%s'" % sce_net
["name"]
1877 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
1878 net_name
= net_name
[:255] #limit length
1879 net_vim_name
= net_name
1880 create_network
= True
1881 lookfor_network
= False
1884 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
1885 if len(vim_nets
) > 1:
1886 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1887 elif len(vim_nets
) == 0:
1888 if not create_network
:
1889 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1891 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
1892 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
1893 create_network
= False
1895 #if network is not external
1896 network_id
= vim
.new_network(net_vim_name
, net_type
, sce_net
.get('ip_profile',None))
1897 sce_net
["vim_id_sites"][datacenter_id
] = network_id
1898 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = network_id
1899 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':network_id
})
1900 sce_net
["created"] = True
1902 #2. Creating new nets (vnf internal nets) in the VIM"
1903 #For each vnf net, we create it and we add it to instanceNetlist.
1904 for sce_vnf
in scenarioDict
['vnfs']:
1905 for net
in sce_vnf
['nets']:
1906 if sce_vnf
.get("datacenter"):
1907 vim
= myvims
[ sce_vnf
["datacenter"] ]
1908 datacenter_id
= sce_vnf
["datacenter"]
1910 vim
= myvims
[ default_datacenter_id
]
1911 datacenter_id
= default_datacenter_id
1912 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
1913 net_name
= descriptor_net
.get("name")
1915 net_name
= "%s.%s" %(instance_name
, net
["name"])
1916 net_name
= net_name
[:255] #limit length
1917 net_type
= net
['type']
1918 network_id
= vim
.new_network(net_name
, net_type
, net
.get('ip_profile',None))
1919 net
['vim_id'] = network_id
1920 if sce_vnf
['uuid'] not in auxNetDict
:
1921 auxNetDict
[sce_vnf
['uuid']] = {}
1922 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1923 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1924 net
["created"] = True
1927 #print "auxNetDict:"
1928 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1930 #3. Creating new vm instances in the VIM
1931 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1932 for sce_vnf
in scenarioDict
['vnfs']:
1933 if sce_vnf
.get("datacenter"):
1934 vim
= myvims
[ sce_vnf
["datacenter"] ]
1935 datacenter_id
= sce_vnf
["datacenter"]
1937 vim
= myvims
[ default_datacenter_id
]
1938 datacenter_id
= default_datacenter_id
1939 sce_vnf
["datacenter_id"] = datacenter_id
1941 for vm
in sce_vnf
['vms']:
1944 myVMDict
['name'] = "{}.{}.{}".format(instance_name
,sce_vnf
['name'],chr(96+i
))
1945 myVMDict
['description'] = myVMDict
['name'][0:99]
1947 # myVMDict['start'] = "no"
1948 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1949 #create image at vim in case it not exist
1950 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1951 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
1952 vm
['vim_image_id'] = image_id
1954 #create flavor at vim in case it not exist
1955 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1956 if flavor_dict
['extended']!=None:
1957 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1958 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
1963 #Obtain information for additional disks
1964 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
1965 if not extended_flavor_dict
:
1966 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
1969 #extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
1970 myVMDict
['disks'] = None
1971 extended_info
= extended_flavor_dict
[0]['extended']
1972 if extended_info
!= None:
1973 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
1974 if 'disks' in extended_flavor_dict_yaml
:
1975 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
1980 vm
['vim_flavor_id'] = flavor_id
1982 myVMDict
['imageRef'] = vm
['vim_image_id']
1983 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1984 myVMDict
['networks'] = []
1985 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
1986 for iface
in vm
['interfaces']:
1988 if iface
['type']=="data":
1989 netDict
['type'] = iface
['model']
1990 elif "model" in iface
and iface
["model"]!=None:
1991 netDict
['model']=iface
['model']
1992 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1993 #discover type of interface looking at flavor
1994 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1995 for flavor_iface
in numa
.get('interfaces',[]):
1996 if flavor_iface
.get('name') == iface
['internal_name']:
1997 if flavor_iface
['dedicated'] == 'yes':
1998 netDict
['type']="PF" #passthrough
1999 elif flavor_iface
['dedicated'] == 'no':
2000 netDict
['type']="VF" #siov
2001 elif flavor_iface
['dedicated'] == 'yes:sriov':
2002 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2003 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2005 netDict
["use"]=iface
['type']
2006 if netDict
["use"]=="data" and not netDict
.get("type"):
2007 #print "netDict", netDict
2008 #print "iface", iface
2009 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'])
2010 if flavor_dict
.get('extended')==None:
2011 raise NfvoException(e_text
+ "After database migration some information is not available. \
2012 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2014 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2015 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2016 netDict
["type"]="virtual"
2017 if "vpci" in iface
and iface
["vpci"] is not None:
2018 netDict
['vpci'] = iface
['vpci']
2019 if "mac" in iface
and iface
["mac"] is not None:
2020 netDict
['mac_address'] = iface
['mac']
2021 if "port-security" in iface
and iface
["port-security"] is not None:
2022 netDict
['port_security'] = iface
['port-security']
2023 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2024 netDict
['floating_ip'] = iface
['floating-ip']
2025 netDict
['name'] = iface
['internal_name']
2026 if iface
['net_id'] is None:
2027 for vnf_iface
in sce_vnf
["interfaces"]:
2030 if vnf_iface
['interface_id']==iface
['uuid']:
2031 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
2034 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2035 #skip bridge ifaces not connected to any net
2036 #if 'net_id' not in netDict or netDict['net_id']==None:
2038 myVMDict
['networks'].append(netDict
)
2039 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2040 #print myVMDict['name']
2041 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2042 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2043 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2044 vm_id
= vim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
2045 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'], cloud_config
= cloud_config
,
2046 disk_list
= myVMDict
['disks'])
2048 vm
['vim_id'] = vm_id
2049 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2050 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2051 for net
in myVMDict
['networks']:
2053 for iface
in vm
['interfaces']:
2054 if net
["name"]==iface
["internal_name"]:
2055 iface
["vim_id"]=net
["vim_id"]
2057 scenarioDict
["datacenter2tenant"] = datacenter2tenant
2058 logger
.debug("create_instance Deployment done scenarioDict: %s",
2059 yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False) )
2060 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
2061 return mydb
.get_instance_scenario(instance_id
)
2062 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2063 message
= rollback(mydb
, myvims
, rollbackList
)
2064 if isinstance(e
, db_base_Exception
):
2065 error_text
= "database Exception"
2066 elif isinstance(e
, vimconn
.vimconnException
):
2067 error_text
= "VIM Exception"
2069 error_text
= "Exception"
2070 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2071 #logger.error("create_instance: %s", error_text)
2072 raise NfvoException(error_text
, e
.http_code
)
2074 def delete_instance(mydb
, tenant_id
, instance_id
):
2075 #print "Checking that the instance_id exists and getting the instance dictionary"
2076 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2077 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2078 tenant_id
= instanceDict
["tenant_id"]
2079 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2081 #1. Delete from Database
2082 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2090 for sce_vnf
in instanceDict
['vnfs']:
2091 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2092 if datacenter_key
not in myvims
:
2093 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2094 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2096 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2097 sce_vnf
["datacenter_tenant_id"]))
2098 myvims
[datacenter_key
] = None
2100 myvims
[datacenter_key
] = vims
.values()[0]
2101 myvim
= myvims
[datacenter_key
]
2102 for vm
in sce_vnf
['vms']:
2104 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2107 myvim
.delete_vminstance(vm
['vim_vm_id'])
2108 except vimconn
.vimconnNotFoundException
as e
:
2109 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2110 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2111 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2112 except vimconn
.vimconnException
as e
:
2113 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2114 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2115 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2119 for net
in instanceDict
['nets']:
2120 if not net
['created']:
2121 continue #skip not created nets
2122 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2123 if datacenter_key
not in myvims
:
2124 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2125 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2127 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2128 myvims
[datacenter_key
] = None
2130 myvims
[datacenter_key
] = vims
.values()[0]
2131 myvim
= myvims
[datacenter_key
]
2134 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2137 myvim
.delete_network(net
['vim_net_id'])
2138 except vimconn
.vimconnNotFoundException
as e
:
2139 error_msg
+="\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2140 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2141 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2142 except vimconn
.vimconnException
as e
:
2143 error_msg
+="\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'], net
["datacenter_id"], e
.http_code
, str(e
))
2144 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2145 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2146 if len(error_msg
)>0:
2147 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2149 return 'instance ' + message
+ ' deleted'
2151 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2152 '''Refreshes a scenario instance. It modifies instanceDict'''
2154 - 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
2157 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2158 #print "nfvo.refresh_instance begins"
2159 #print json.dumps(instanceDict, indent=4)
2161 #print "Getting the VIM URL and the VIM tenant_id"
2164 # 1. Getting VIM vm and net list
2165 vms_updated
= [] #List of VM instance uuids in openmano that were updated
2168 for sce_vnf
in instanceDict
['vnfs']:
2169 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2170 if datacenter_key
not in vm_list
:
2171 vm_list
[datacenter_key
] = []
2172 if datacenter_key
not in myvims
:
2173 vims
= get_vim(mydb
, nfvo_tenant
, datacenter_id
=sce_vnf
["datacenter_id"],
2174 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2176 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"]))
2177 myvims
[datacenter_key
] = None
2179 myvims
[datacenter_key
] = vims
.values()[0]
2180 for vm
in sce_vnf
['vms']:
2181 vm_list
[datacenter_key
].append(vm
['vim_vm_id'])
2182 vms_notupdated
.append(vm
["uuid"])
2184 nets_updated
= [] #List of VM instance uuids in openmano that were updated
2187 for net
in instanceDict
['nets']:
2188 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2189 if datacenter_key
not in net_list
:
2190 net_list
[datacenter_key
] = []
2191 if datacenter_key
not in myvims
:
2192 vims
= get_vim(mydb
, nfvo_tenant
, datacenter_id
=net
["datacenter_id"],
2193 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2195 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2196 myvims
[datacenter_key
] = None
2198 myvims
[datacenter_key
] = vims
.values()[0]
2200 net_list
[datacenter_key
].append(net
['vim_net_id'])
2201 nets_notupdated
.append(net
["uuid"])
2203 # 1. Getting the status of all VMs
2205 for datacenter_key
in myvims
:
2206 if not vm_list
.get(datacenter_key
):
2210 if not myvims
[datacenter_key
]:
2211 failed_message
= "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"])
2214 vm_dict
.update(myvims
[datacenter_key
].refresh_vms_status(vm_list
[datacenter_key
]) )
2216 except vimconn
.vimconnException
as e
:
2217 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
2218 failed_message
= str(e
)
2220 for vm
in vm_list
[datacenter_key
]:
2221 vm_dict
[vm
] = {'status': "VIM_ERROR", 'error_msg': failed_message
}
2223 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2224 for sce_vnf
in instanceDict
['vnfs']:
2225 for vm
in sce_vnf
['vms']:
2226 vm_id
= vm
['vim_vm_id']
2227 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
2228 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2229 has_mgmt_iface
= False
2230 for iface
in vm
["interfaces"]:
2231 if iface
["type"]=="mgmt":
2232 has_mgmt_iface
= True
2233 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
2234 vm_dict
[vm_id
]['status'] = "ACTIVE"
2235 if vm_dict
[vm_id
].get('error_msg') and len(vm_dict
[vm_id
]['error_msg']) >= 1024:
2236 vm_dict
[vm_id
]['error_msg'] = vm_dict
[vm_id
]['error_msg'][:516] + " ... " + vm_dict
[vm_id
]['error_msg'][-500:]
2237 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'):
2238 vm
['status'] = vm_dict
[vm_id
]['status']
2239 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
2240 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
2241 # 2.1. Update in openmano DB the VMs whose status changed
2243 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
2244 vms_notupdated
.remove(vm
["uuid"])
2246 vms_updated
.append(vm
["uuid"])
2247 except db_base_Exception
as e
:
2248 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2249 # 2.2. Update in openmano DB the interface VMs
2250 for interface
in interfaces
:
2251 #translate from vim_net_id to instance_net_id
2253 for net
in instanceDict
['nets']:
2254 if net
["vim_net_id"] == interface
["vim_net_id"]:
2255 network_id_list
.append(net
["uuid"])
2256 if not network_id_list
:
2258 del interface
["vim_net_id"]
2260 for network_id
in network_id_list
:
2261 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
2262 except db_base_Exception
as e
:
2263 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
2265 # 3. Getting the status of all nets
2267 for datacenter_key
in myvims
:
2268 if not net_list
.get(datacenter_key
):
2272 if not myvims
[datacenter_key
]:
2273 failed_message
= "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"])
2276 net_dict
.update(myvims
[datacenter_key
].refresh_nets_status(net_list
[datacenter_key
]) )
2278 except vimconn
.vimconnException
as e
:
2279 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
2280 failed_message
= str(e
)
2282 for net
in net_list
[datacenter_key
]:
2283 net_dict
[net
] = {'status': "VIM_ERROR", 'error_msg': failed_message
}
2285 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2286 # TODO: update nets inside a vnf
2287 for net
in instanceDict
['nets']:
2288 net_id
= net
['vim_net_id']
2289 if net_dict
[net_id
].get('error_msg') and len(net_dict
[net_id
]['error_msg']) >= 1024:
2290 net_dict
[net_id
]['error_msg'] = net_dict
[net_id
]['error_msg'][:516] + " ... " + net_dict
[vm_id
]['error_msg'][-500:]
2291 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'):
2292 net
['status'] = net_dict
[net_id
]['status']
2293 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
2294 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
2295 # 5.1. Update in openmano DB the nets whose status changed
2297 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
2298 nets_notupdated
.remove(net
["uuid"])
2300 nets_updated
.append(net
["uuid"])
2301 except db_base_Exception
as e
:
2302 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2304 # Returns appropriate output
2305 #print "nfvo.refresh_instance finishes"
2306 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2307 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
2308 instance_id
= instanceDict
['uuid']
2309 if len(vms_notupdated
)+len(nets_notupdated
)>0:
2310 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
2311 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
2313 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2315 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2316 #print "Checking that the instance_id exists and getting the instance dictionary"
2317 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2318 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2320 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2321 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2323 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2324 myvim
= vims
.values()[0]
2327 input_vnfs
= action_dict
.pop("vnfs", [])
2328 input_vms
= action_dict
.pop("vms", [])
2329 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2333 for sce_vnf
in instanceDict
['vnfs']:
2334 for vm
in sce_vnf
['vms']:
2335 if not action_over_all
:
2336 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2337 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2340 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2341 if "console" in action_dict
:
2342 if not global_config
["http_console_proxy"]:
2343 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2344 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2345 protocol
=data
["protocol"],
2346 ip
= data
["server"],
2347 port
= data
["port"],
2348 suffix
= data
["suffix"]),
2352 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2353 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2354 "description": "this console is only reachable by local interface",
2359 #print "console data", data
2361 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2362 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2363 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2364 protocol
=data
["protocol"],
2365 ip
= global_config
["http_console_host"],
2366 port
= console_thread
.port
,
2367 suffix
= data
["suffix"]),
2371 except NfvoException
as e
:
2372 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2376 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2378 except vimconn
.vimconnException
as e
:
2379 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2382 if vm_ok
==0: #all goes wrong
2387 def create_or_use_console_proxy_thread(console_server
, console_port
):
2388 #look for a non-used port
2389 console_thread_key
= console_server
+ ":" + str(console_port
)
2390 if console_thread_key
in global_config
["console_thread"]:
2391 #global_config["console_thread"][console_thread_key].start_timeout()
2392 return global_config
["console_thread"][console_thread_key
]
2394 for port
in global_config
["console_port_iterator"]():
2395 #print "create_or_use_console_proxy_thread() port:", port
2396 if port
in global_config
["console_ports"]:
2399 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2401 global_config
["console_thread"][console_thread_key
] = clithread
2402 global_config
["console_ports"][port
] = console_thread_key
2404 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2405 #port used, try with onoher
2407 except cli
.ConsoleProxyException
as e
:
2408 raise NfvoException(str(e
), HTTP_Bad_Request
)
2409 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2411 def check_tenant(mydb
, tenant_id
):
2412 '''check that tenant exists at database'''
2413 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2415 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2418 def new_tenant(mydb
, tenant_dict
):
2419 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2422 def delete_tenant(mydb
, tenant
):
2423 #get nfvo_tenant info
2425 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2426 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2427 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2429 def new_datacenter(mydb
, datacenter_descriptor
):
2430 if "config" in datacenter_descriptor
:
2431 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2432 #Check that datacenter-type is correct
2433 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2436 module
= "vimconn_" + datacenter_type
2437 module_info
= imp
.find_module(module
)
2438 except (IOError, ImportError):
2439 if module_info
and module_info
[0]:
2440 file.close(module_info
[0])
2441 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2443 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2444 return datacenter_id
2446 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2447 #obtain data, check that only one exist
2448 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2450 datacenter_id
= datacenter
['uuid']
2451 where
={'uuid': datacenter
['uuid']}
2452 if "config" in datacenter_descriptor
:
2453 if datacenter_descriptor
['config']!=None:
2455 new_config_dict
= datacenter_descriptor
["config"]
2458 for k
in new_config_dict
:
2459 if new_config_dict
[k
]==None:
2462 config_dict
= yaml
.load(datacenter
["config"])
2463 config_dict
.update(new_config_dict
)
2467 except Exception as e
:
2468 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2469 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2470 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2471 return datacenter_id
2473 def delete_datacenter(mydb
, datacenter
):
2474 #get nfvo_tenant info
2475 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2476 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2477 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2479 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):
2480 #get datacenter info
2481 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2482 datacenter_name
=myvim
["name"]
2484 create_vim_tenant
=True if vim_tenant_id
==None and vim_tenant_name
==None else False
2486 #get nfvo_tenant info
2487 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2488 if vim_tenant_name
==None:
2489 vim_tenant_name
=tenant_dict
['name']
2491 #check that this association does not exist before
2492 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2493 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2494 if len(tenants_datacenters
)>0:
2495 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2497 vim_tenant_id_exist_atdb
=False
2498 if not create_vim_tenant
:
2499 where_
={"datacenter_id": datacenter_id
}
2500 if vim_tenant_id
!=None:
2501 where_
["vim_tenant_id"] = vim_tenant_id
2502 if vim_tenant_name
!=None:
2503 where_
["vim_tenant_name"] = vim_tenant_name
2504 #check if vim_tenant_id is already at database
2505 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2506 if len(datacenter_tenants_dict
)>=1:
2507 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2508 vim_tenant_id_exist_atdb
=True
2509 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2511 datacenter_tenants_dict
= {}
2512 #insert at table datacenter_tenants
2513 else: #if vim_tenant_id==None:
2514 #create tenant at VIM if not provided
2516 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2517 except vimconn
.vimconnException
as e
:
2518 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2519 datacenter_tenants_dict
= {}
2520 datacenter_tenants_dict
["created"]="true"
2522 #fill datacenter_tenants table
2523 if not vim_tenant_id_exist_atdb
:
2524 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2525 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2526 datacenter_tenants_dict
["user"] = vim_username
2527 datacenter_tenants_dict
["passwd"] = vim_password
2528 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2530 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
2531 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2532 datacenter_tenants_dict
["uuid"] = id_
2534 #fill tenants_datacenters table
2535 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2536 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2537 return datacenter_id
2539 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2540 #get datacenter info
2541 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2543 #get nfvo_tenant info
2544 if not tenant_id
or tenant_id
=="any":
2547 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2548 tenant_uuid
= tenant_dict
['uuid']
2550 #check that this association exist before
2551 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2553 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2554 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2555 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2556 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2558 #delete this association
2559 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2561 #get vim_tenant info and deletes
2563 for tenant_datacenter_item
in tenant_datacenter_list
:
2564 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2565 #try to delete vim:tenant
2567 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2568 if vim_tenant_dict
['created']=='true':
2569 #delete tenant at VIM if created by NFVO
2571 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2572 except vimconn
.vimconnException
as e
:
2573 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2574 logger
.warn(warning
)
2575 except db_base_Exception
as e
:
2576 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2577 pass #the error will be caused because dependencies, vim_tenant can not be deleted
2579 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2581 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2583 #get datacenter info
2584 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2586 if 'net-update' in action_dict
:
2588 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2590 except vimconn
.vimconnException
as e
:
2591 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2592 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2593 #update nets Change from VIM format to NFVO format
2596 net_nfvo
={'datacenter_id': datacenter_id
}
2597 net_nfvo
['name'] = net
['name']
2598 #net_nfvo['description']= net['name']
2599 net_nfvo
['vim_net_id'] = net
['id']
2600 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2601 net_nfvo
['shared'] = net
['shared']
2602 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2603 net_list
.append(net_nfvo
)
2604 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2605 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2607 elif 'net-edit' in action_dict
:
2608 net
= action_dict
['net-edit'].pop('net')
2609 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2610 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2611 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2613 elif 'net-delete' in action_dict
:
2614 net
= action_dict
['net-deelte'].get('net')
2615 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2616 result
= mydb
.delete_row(FROM
='datacenter_nets',
2617 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2621 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2623 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2624 #get datacenter info
2625 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2627 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2628 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2629 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2632 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2633 #get datacenter info
2634 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2637 action_dict
= action_dict
["netmap"]
2638 if 'vim_id' in action_dict
:
2639 filter_dict
["id"] = action_dict
['vim_id']
2640 if 'vim_name' in action_dict
:
2641 filter_dict
["name"] = action_dict
['vim_name']
2643 filter_dict
["shared"] = True
2646 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
2647 except vimconn
.vimconnException
as e
:
2648 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
2649 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2650 if len(vim_nets
)>1 and action_dict
:
2651 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
2652 elif len(vim_nets
)==0: # and action_dict:
2653 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
2655 for net
in vim_nets
:
2656 net_nfvo
={'datacenter_id': datacenter_id
}
2657 if action_dict
and "name" in action_dict
:
2658 net_nfvo
['name'] = action_dict
['name']
2660 net_nfvo
['name'] = net
['name']
2661 #net_nfvo['description']= net['name']
2662 net_nfvo
['vim_net_id'] = net
['id']
2663 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2664 net_nfvo
['shared'] = net
['shared']
2665 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2667 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2668 net_nfvo
["status"] = "OK"
2669 net_nfvo
["uuid"] = net_id
2670 except db_base_Exception
as e
:
2674 net_nfvo
["status"] = "FAIL: " + str(e
)
2675 net_list
.append(net_nfvo
)
2678 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2679 #get datacenter info
2680 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2683 if utils
.check_valid_uuid(name
):
2684 filter_dict
["id"] = name
2686 filter_dict
["name"] = name
2688 if item
=="networks":
2689 #filter_dict['tenant_id'] = myvim['tenant_id']
2690 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2691 elif item
=="tenants":
2692 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2694 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2695 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
2696 if name
and len(content
)==1:
2697 return {item
[:-1]: content
[0]}
2698 elif name
and len(content
)==0:
2699 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
2702 return {item
: content
}
2703 except vimconn
.vimconnException
as e
:
2704 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
2705 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
2707 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
2708 #get datacenter info
2709 if tenant_id
== "any":
2712 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2714 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2715 logger
.debug("vim_action_delete vim response: " + str(content
))
2716 items
= content
.values()[0]
2717 if type(items
)==list and len(items
)==0:
2718 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
2719 elif type(items
)==list and len(items
)>1:
2720 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
2721 else: # it is a dict
2722 item_id
= items
["id"]
2723 item_name
= str(items
.get("name"))
2726 if item
=="networks":
2727 content
= myvim
.delete_network(item_id
)
2728 elif item
=="tenants":
2729 content
= myvim
.delete_tenant(item_id
)
2731 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2732 except vimconn
.vimconnException
as e
:
2733 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
2734 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
2736 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
2738 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2739 #get datacenter info
2740 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
2741 if tenant_id
== "any":
2743 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2745 if item
=="networks":
2746 net
= descriptor
["network"]
2747 net_name
= net
.pop("name")
2748 net_type
= net
.pop("type", "bridge")
2749 net_public
= net
.pop("shared", False)
2750 net_ipprofile
= net
.pop("ip_profile", None)
2751 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, **net
)
2752 elif item
=="tenants":
2753 tenant
= descriptor
["tenant"]
2754 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2756 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2757 except vimconn
.vimconnException
as e
:
2758 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
2760 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)