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
47 vimconn_imported
={} #dictionary with VIM type as key, loaded module as value
48 logger
= logging
.getLogger('openmano.nfvo')
50 class NfvoException(Exception):
51 def __init__(self
, message
, http_code
):
52 self
.http_code
= http_code
53 Exception.__init
__(self
, message
)
56 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
58 return result, content:
59 <0, error_text upon error
60 nb_records, flavor_list on success
63 WHERE_dict
['vnf_id'] = vnf_id
64 if nfvo_tenant
is not None:
65 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
67 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
68 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
69 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
70 #print "get_flavor_list result:", result
71 #print "get_flavor_list content:", content
73 for flavor
in flavors
:
74 flavorList
.append(flavor
['flavor_id'])
77 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
79 return result, content:
80 <0, error_text upon error
81 nb_records, flavor_list on success
84 WHERE_dict
['vnf_id'] = vnf_id
85 if nfvo_tenant
is not None:
86 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
88 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
89 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
92 imageList
.append(image
['image_id'])
95 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
96 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
97 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
98 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
99 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
100 raise exception upon error
103 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
104 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
105 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
106 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
107 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
108 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
109 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
110 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'
111 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
112 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
115 from_
= 'datacenters as d'
116 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
118 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
121 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
122 if vim
["config"] != None:
123 extra
.update(yaml
.load(vim
["config"]))
124 if vim
["type"] not in vimconn_imported
:
127 module
= "vimconn_" + vim
["type"]
128 module_info
= imp
.find_module(module
)
129 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
130 vimconn_imported
[vim
["type"]] = vim_conn
131 except (IOError, ImportError) as e
:
132 if module_info
and module_info
[0]:
133 file.close(module_info
[0])
134 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
135 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
139 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
140 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
141 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
142 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
), tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
143 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
144 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
147 except Exception as e
:
148 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
150 except db_base_Exception
as e
:
151 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
153 def rollback(mydb
, vims
, rollback_list
):
155 #delete things by reverse order
156 for i
in range(len(rollback_list
)-1, -1, -1):
157 item
= rollback_list
[i
]
158 if item
["where"]=="vim":
159 if item
["vim_id"] not in vims
:
161 vim
=vims
[ item
["vim_id"] ]
163 if item
["what"]=="image":
164 vim
.delete_image(item
["uuid"])
165 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
166 elif item
["what"]=="flavor":
167 vim
.delete_flavor(item
["uuid"])
168 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
169 elif item
["what"]=="network":
170 vim
.delete_network(item
["uuid"])
171 elif item
["what"]=="vm":
172 vim
.delete_vminstance(item
["uuid"])
173 except vimconn
.vimconnException
as e
:
174 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
175 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
176 except db_base_Exception
as e
:
177 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
181 if item
["what"]=="image":
182 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
183 elif item
["what"]=="flavor":
184 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
185 except db_base_Exception
as e
:
186 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
187 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
188 if len(undeleted_items
)==0:
189 return True," Rollback successful."
191 return False," Rollback fails to delete: " + str(undeleted_items
)
193 def check_vnf_descriptor(vnf_descriptor
):
195 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
197 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
199 #dataplane interfaces
200 for numa
in vnfc
.get("numas",() ):
201 for interface
in numa
.get("interfaces",()):
202 if interface
["name"] in name_list
:
203 raise NfvoException("Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC"\
204 .format(vnfc
["name"], interface
["name"]),
206 name_list
.append( interface
["name"] )
208 for interface
in vnfc
.get("bridge-ifaces",() ):
209 if interface
["name"] in name_list
:
210 raise NfvoException("Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC"\
211 .format(vnfc
["name"], interface
["name"]),
213 name_list
.append( interface
["name"] )
214 vnfc_interfaces
[ vnfc
["name"] ] = name_list
216 #check if the info in external_connections matches with the one in the vnfcs
218 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
219 if external_connection
["name"] in name_list
:
220 raise NfvoException("Error at vnf:external-connections:name, value '{}' already used as an external-connection"\
221 .format(external_connection
["name"]),
223 name_list
.append(external_connection
["name"])
224 if external_connection
["VNFC"] not in vnfc_interfaces
:
225 raise NfvoException("Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC"\
226 .format(external_connection
["name"], external_connection
["VNFC"]),
229 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
230 raise NfvoException("Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC"\
231 .format(external_connection
["name"], external_connection
["local_iface_name"]),
234 #check if the info in internal_connections matches with the one in the vnfcs
236 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
237 if internal_connection
["name"] in name_list
:
238 raise NfvoException("Error at vnf:internal-connections:name, value '%s' already used as an internal-connection"\
239 .format(internal_connection
["name"]),
241 name_list
.append(internal_connection
["name"])
242 #We should check that internal-connections of type "ptp" have only 2 elements
243 if len(internal_connection
["elements"])>2 and internal_connection
["type"] == "ptp":
244 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements, size must be 2 for a type:'ptp'"\
245 .format(internal_connection
["name"]),
247 for port
in internal_connection
["elements"]:
248 if port
["VNFC"] not in vnfc_interfaces
:
249 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC"\
250 .format(internal_connection
["name"], port
["VNFC"]),
252 if port
["local_iface_name"] not in vnfc_interfaces
[ port
["VNFC"] ]:
253 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC"\
254 .format(internal_connection
["name"], port
["local_iface_name"]),
256 return -HTTP_Bad_Request
,
258 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
260 if only_create_at_vim
:
261 image_mano_id
= image_dict
['uuid']
262 if return_on_error
== None:
263 return_on_error
= True
265 if image_dict
['location'] is not None:
266 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
268 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
270 image_mano_id
= images
[0]['uuid']
273 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
274 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
275 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
277 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
278 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
279 #create image at every vim
280 for vim_id
,vim
in vims
.iteritems():
281 image_created
="false"
283 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
284 #look at VIM if this image exist
286 if image_dict
['location'] is not None:
287 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
290 filter_dict
['name']=image_dict
['universal_name']
291 filter_dict
['checksum']=image_dict
['checksum']
292 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
293 vim_images
= vim
.get_image_list(filter_dict
)
294 if len(vim_images
) > 1:
295 raise NfvoException("More than one candidate VIM image found for filter: " + str(filter_dict
), HTTP_Conflict
)
296 elif len(vim_images
) == 0:
297 raise NfvoException("Image not found at VIM with filter: '%s'", str(filter_dict
))
299 image_vim_id
= vim_images
[0].id
301 except vimconn
.vimconnNotFoundException
as e
:
302 #Create the image in VIM
304 image_vim_id
= vim
.new_image(image_dict
)
305 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
307 except vimconn
.vimconnException
as e
:
309 logger
.error("Error creating image at VIM: %s", str(e
))
312 logger
.warn("Error creating image at VIM: %s", str(e
))
314 except vimconn
.vimconnException
as e
:
316 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
318 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
321 #if we reach here, the image has been created or existed
323 #add new vim_id at datacenters_images
324 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
325 elif image_db
[0]["vim_id"]!=image_vim_id
:
326 #modify existing vim_id at datacenters_images
327 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
329 return image_vim_id
if only_create_at_vim
else image_mano_id
331 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
332 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
333 'ram':flavor_dict
.get('ram'),
334 'vcpus':flavor_dict
.get('vcpus'),
336 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
337 del flavor_dict
['extended']
338 if 'extended' in flavor_dict
:
339 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
341 #look if flavor exist
342 if only_create_at_vim
:
343 flavor_mano_id
= flavor_dict
['uuid']
344 if return_on_error
== None:
345 return_on_error
= True
347 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
349 flavor_mano_id
= flavors
[0]['uuid']
352 #create one by one the images of aditional disks
353 dev_image_list
=[] #list of images
354 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
356 for device
in flavor_dict
['extended'].get('devices',[]):
357 if "image" not in device
and "image name" not in device
:
360 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
361 image_dict
['universal_name']=device
.get('image name')
362 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
363 image_dict
['location']=device
.get('image')
364 image_dict
['checksum']=device
.get('image checksum')
365 image_metadata_dict
= device
.get('image metadata', None)
366 image_metadata_str
= None
367 if image_metadata_dict
!= None:
368 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
369 image_dict
['metadata']=image_metadata_str
370 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
371 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
372 dev_image_list
.append(image_id
)
374 temp_flavor_dict
['name'] = flavor_dict
['name']
375 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
376 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
377 flavor_mano_id
= content
378 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
379 #create flavor at every vim
380 if 'uuid' in flavor_dict
:
381 del flavor_dict
['uuid']
383 for vim_id
,vim
in vims
.items():
384 flavor_created
="false"
386 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
387 #look at VIM if this flavor exist SKIPPED
388 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
390 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
394 #Create the flavor in VIM
395 #Translate images at devices from MANO id to VIM id
396 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
397 #make a copy of original devices
399 for device
in flavor_dict
["extended"].get("devices",[]):
402 devices_original
.append(dev
)
403 if 'image' in device
:
405 if 'image metadata' in device
:
406 del device
['image metadata']
408 for index
in range(0,len(devices_original
)) :
409 device
=devices_original
[index
]
410 if "image" not in device
or "image name" not in device
:
413 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
414 image_dict
['universal_name']=device
.get('image name')
415 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
416 image_dict
['location']=device
.get('image')
417 image_dict
['checksum']=device
.get('image checksum')
418 image_metadata_dict
= device
.get('image metadata', None)
419 image_metadata_str
= None
420 if image_metadata_dict
!= None:
421 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
422 image_dict
['metadata']=image_metadata_str
423 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
424 image_dict
["uuid"]=image_mano_id
425 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
426 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
429 #check that this vim_id exist in VIM, if not create
430 flavor_vim_id
=flavor_db
[0]["vim_id"]
432 vim
.get_flavor(flavor_vim_id
)
433 continue #flavor exist
434 except vimconn
.vimconnException
:
436 #create flavor at vim
437 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
439 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
440 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
441 flavor_created
="true"
442 except vimconn
.vimconnException
as e
:
444 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
446 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
449 #if reach here the flavor has been create or exist
450 if len(flavor_db
)==0:
451 #add new vim_id at datacenters_flavors
452 mydb
.new_row('datacenters_flavors', {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
, 'created':flavor_created
})
453 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
454 #modify existing vim_id at datacenters_flavors
455 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
457 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
459 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
462 # Step 1. Check the VNF descriptor
463 check_vnf_descriptor(vnf_descriptor
)
464 # Step 2. Check tenant exist
465 if tenant_id
!= "any":
466 check_tenant(mydb
, tenant_id
)
467 if "tenant_id" in vnf_descriptor
["vnf"]:
468 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
469 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
472 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
473 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
474 vims
= get_vim(mydb
, tenant_id
)
478 # Step 4. Review the descriptor and add missing fields
479 #print vnf_descriptor
480 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
481 vnf_name
= vnf_descriptor
['vnf']['name']
482 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
483 if "physical" in vnf_descriptor
['vnf']:
484 del vnf_descriptor
['vnf']['physical']
485 #print vnf_descriptor
486 # Step 5. Check internal connections
487 # TODO: to be moved to step 1????
488 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
489 for ic
in internal_connections
:
490 if len(ic
['elements'])>2 and ic
['type']=='ptp':
491 raise NfvoException("Mismatch 'type':'ptp' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'data'".format(len(ic
), ic
['name']),
493 elif len(ic
['elements'])==2 and ic
['type']=='data':
494 raise NfvoException("Mismatch 'type':'data' with 2 elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'ptp'".format(ic
['name']),
497 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
498 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
499 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
501 #For each VNFC, we add it to the VNFCDict and we create a flavor.
502 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
503 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
505 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
506 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
508 VNFCitem
["name"] = vnfc
['name']
509 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
511 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
514 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
515 myflavorDict
["description"] = VNFCitem
["description"]
516 myflavorDict
["ram"] = vnfc
.get("ram", 0)
517 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
518 myflavorDict
["disk"] = vnfc
.get("disk", 1)
519 myflavorDict
["extended"] = {}
521 devices
= vnfc
.get("devices")
523 myflavorDict
["extended"]["devices"] = devices
526 # 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
527 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
529 # Previous code has been commented
530 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
531 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
532 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
533 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
535 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
537 # print "Error creating flavor: unknown processor model. Rollback successful."
538 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
540 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
541 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
543 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
544 myflavorDict
['extended']['numas'] = vnfc
['numas']
548 # Step 6.2 New flavors are created in the VIM
549 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
551 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
552 VNFCitem
["flavor_id"] = flavor_id
553 VNFCDict
[vnfc
['name']] = VNFCitem
555 logger
.debug("Creating new images in the VIM for each VNFC")
556 # Step 6.3 New images are created in the VIM
557 #For each VNFC, we must create the appropriate image.
558 #This "for" loop might be integrated with the previous one
559 #In case this integration is made, the VNFCDict might become a VNFClist.
560 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
561 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
563 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
564 image_dict
['universal_name']=vnfc
.get('image name')
565 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
566 image_dict
['location']=vnfc
.get('VNFC image')
567 image_dict
['checksum']=vnfc
.get('image checksum')
568 image_metadata_dict
= vnfc
.get('image metadata', None)
569 image_metadata_str
= None
570 if image_metadata_dict
is not None:
571 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
572 image_dict
['metadata']=image_metadata_str
573 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
574 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
575 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
576 VNFCDict
[vnfc
['name']]["image_id"] = image_id
577 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
580 # Step 7. Storing the VNF descriptor in the repository
581 if "descriptor" not in vnf_descriptor
["vnf"]:
582 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
584 # Step 8. Adding the VNF to the NFVO DB
585 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
587 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
588 _
, message
= rollback(mydb
, vims
, rollback_list
)
589 if isinstance(e
, db_base_Exception
):
590 error_text
= "Exception at database"
591 elif isinstance(e
, KeyError):
592 error_text
= "KeyError exception "
593 e
.http_code
= HTTP_Internal_Server_Error
595 error_text
= "Exception at VIM"
596 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
597 #logger.error("start_scenario %s", error_text)
598 raise NfvoException(error_text
, e
.http_code
)
600 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
603 # Step 1. Check the VNF descriptor
604 check_vnf_descriptor(vnf_descriptor
)
605 # Step 2. Check tenant exist
606 if tenant_id
!= "any":
607 check_tenant(mydb
, tenant_id
)
608 if "tenant_id" in vnf_descriptor
["vnf"]:
609 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
610 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
613 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
614 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
615 vims
= get_vim(mydb
, tenant_id
)
619 # Step 4. Review the descriptor and add missing fields
620 #print vnf_descriptor
621 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
622 vnf_name
= vnf_descriptor
['vnf']['name']
623 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
624 if "physical" in vnf_descriptor
['vnf']:
625 del vnf_descriptor
['vnf']['physical']
626 #print vnf_descriptor
627 # Step 5. Check internal connections
628 # TODO: to be moved to step 1????
629 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
630 for ic
in internal_connections
:
631 if len(ic
['elements'])>2 and ic
['type']=='e-line':
632 raise NfvoException("Mismatch 'type':'e-line' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'e-lan'".format(len(ic
), ic
['name']),
635 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
636 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
637 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
639 #For each VNFC, we add it to the VNFCDict and we create a flavor.
640 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
641 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
643 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
644 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
646 VNFCitem
["name"] = vnfc
['name']
647 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
649 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
652 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
653 myflavorDict
["description"] = VNFCitem
["description"]
654 myflavorDict
["ram"] = vnfc
.get("ram", 0)
655 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
656 myflavorDict
["disk"] = vnfc
.get("disk", 1)
657 myflavorDict
["extended"] = {}
659 devices
= vnfc
.get("devices")
661 myflavorDict
["extended"]["devices"] = devices
664 # 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
665 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
667 # Previous code has been commented
668 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
669 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
670 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
671 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
673 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
675 # print "Error creating flavor: unknown processor model. Rollback successful."
676 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
678 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
679 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
681 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
682 myflavorDict
['extended']['numas'] = vnfc
['numas']
686 # Step 6.2 New flavors are created in the VIM
687 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
689 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
690 VNFCitem
["flavor_id"] = flavor_id
691 VNFCDict
[vnfc
['name']] = VNFCitem
693 logger
.debug("Creating new images in the VIM for each VNFC")
694 # Step 6.3 New images are created in the VIM
695 #For each VNFC, we must create the appropriate image.
696 #This "for" loop might be integrated with the previous one
697 #In case this integration is made, the VNFCDict might become a VNFClist.
698 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
699 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
701 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
702 image_dict
['universal_name']=vnfc
.get('image name')
703 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
704 image_dict
['location']=vnfc
.get('VNFC image')
705 image_dict
['checksum']=vnfc
.get('image checksum')
706 image_metadata_dict
= vnfc
.get('image metadata', None)
707 image_metadata_str
= None
708 if image_metadata_dict
is not None:
709 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
710 image_dict
['metadata']=image_metadata_str
711 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
712 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
713 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
714 VNFCDict
[vnfc
['name']]["image_id"] = image_id
715 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
718 # Step 7. Storing the VNF descriptor in the repository
719 if "descriptor" not in vnf_descriptor
["vnf"]:
720 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
722 # Step 8. Adding the VNF to the NFVO DB
723 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
725 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
726 _
, message
= rollback(mydb
, vims
, rollback_list
)
727 if isinstance(e
, db_base_Exception
):
728 error_text
= "Exception at database"
729 elif isinstance(e
, KeyError):
730 error_text
= "KeyError exception "
731 e
.http_code
= HTTP_Internal_Server_Error
733 error_text
= "Exception at VIM"
734 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
735 #logger.error("start_scenario %s", error_text)
736 raise NfvoException(error_text
, e
.http_code
)
738 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
739 #check valid tenant_id
740 check_tenant(mydb
, tenant_id
)
743 if tenant_id
!= "any":
744 where_or
["tenant_id"] = tenant_id
745 where_or
["public"] = True
746 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
749 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
750 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
751 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
752 data
={'vnf' : filtered_content
}
754 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
755 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description'),
756 WHERE
={'vnfs.uuid': vnf_id
} )
758 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
760 data
['vnf']['VNFC'] = content
761 #TODO: GET all the information from a VNFC and include it in the output.
764 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
765 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
766 WHERE
={'vnfs.uuid': vnf_id
} )
767 data
['vnf']['nets'] = content
769 #GET ip-profile for each net
770 for net
in data
['vnf']['nets']:
771 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
772 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
773 WHERE
={'net_id': net
["uuid"]} )
774 if len(ipprofiles
)==1:
775 net
["ip_profile"] = ipprofiles
[0]
776 elif len(ipprofiles
)>1:
777 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
780 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
782 #GET External Interfaces
783 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
784 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
785 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
786 WHERE
={'vnfs.uuid': vnf_id
},
787 WHERE_NOT
={'interfaces.external_name': None} )
789 data
['vnf']['external-connections'] = content
794 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
796 if tenant_id
!= "any":
797 check_tenant(mydb
, tenant_id
)
798 # Get the URL of the VIM from the nfvo_tenant and the datacenter
799 vims
= get_vim(mydb
, tenant_id
)
803 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
805 if tenant_id
!= "any":
806 where_or
["tenant_id"] = tenant_id
807 where_or
["public"] = True
808 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
811 # "Getting the list of flavors and tenants of the VNF"
812 flavorList
= get_flavorlist(mydb
, vnf_id
)
813 if len(flavorList
)==0:
814 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
816 imageList
= get_imagelist(mydb
, vnf_id
)
817 if len(imageList
)==0:
818 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
820 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
822 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
825 for flavor
in flavorList
:
826 #check if flavor is used by other vnf
828 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
830 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
832 #flavor not used, must be deleted
834 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
836 if flavor_vim
["datacenter_id"] not in vims
:
838 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
840 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
842 myvim
.delete_flavor(flavor_vim
["vim_id"])
843 except vimconn
.vimconnNotFoundException
as e
:
844 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
845 except vimconn
.vimconnException
as e
:
846 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
847 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
848 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
849 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
850 mydb
.delete_row_by_id('flavors', flavor
)
851 except db_base_Exception
as e
:
852 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
853 undeletedItems
.append("flavor %s" % flavor
)
856 for image
in imageList
:
858 #check if image is used by other vnf
859 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
861 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
863 #image not used, must be deleted
865 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
867 if image_vim
["datacenter_id"] not in vims
:
869 if image_vim
['created']=='false': #skip this image because not created by openmano
871 myvim
=vims
[ image_vim
["datacenter_id"] ]
873 myvim
.delete_image(image_vim
["vim_id"])
874 except vimconn
.vimconnNotFoundException
as e
:
875 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
876 except vimconn
.vimconnException
as e
:
877 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
878 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
879 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
880 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
881 mydb
.delete_row_by_id('images', image
)
882 except db_base_Exception
as e
:
883 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
884 undeletedItems
.append("image %s" % image
)
886 return vnf_id
+ " " + vnf
["name"]
888 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
890 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
891 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
895 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
896 myvim
= vims
.values()[0]
897 result
,servers
= myvim
.get_hosts_info()
899 return result
, servers
900 topology
= {'name':myvim
['name'] , 'servers': servers
}
901 return result
, topology
903 def get_hosts(mydb
, nfvo_tenant_id
):
904 vims
= get_vim(mydb
, nfvo_tenant_id
)
906 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
908 #print "nfvo.datacenter_action() error. Several datacenters found"
909 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
910 myvim
= vims
.values()[0]
912 hosts
= myvim
.get_hosts()
913 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
915 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
917 server
={'name':host
['name'], 'vms':[]}
918 for vm
in host
['instances']:
919 #get internal name and model
921 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
922 WHERE
={'vim_vm_id':vm
['id']} )
924 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
926 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
928 except db_base_Exception
as e
:
929 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
930 datacenter
['Datacenters'][0]['servers'].append(server
)
931 #return -400, "en construccion"
933 #print 'datacenters '+ json.dumps(datacenter, indent=4)
935 except vimconn
.vimconnException
as e
:
936 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
938 def new_scenario(mydb
, tenant_id
, topo
):
940 # result, vims = get_vim(mydb, tenant_id)
942 # return result, vims
944 if tenant_id
!= "any":
945 check_tenant(mydb
, tenant_id
)
946 if "tenant_id" in topo
:
947 if topo
["tenant_id"] != tenant_id
:
948 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
953 #1.1: get VNFs and external_networks (other_nets).
955 other_nets
={} #external_networks, bridge_networks and data_networkds
956 nodes
= topo
['topology']['nodes']
957 for k
in nodes
.keys():
958 if nodes
[k
]['type'] == 'VNF':
960 vnfs
[k
]['ifaces'] = {}
961 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
962 other_nets
[k
] = nodes
[k
]
963 other_nets
[k
]['external']=True
964 elif nodes
[k
]['type'] == 'network':
965 other_nets
[k
] = nodes
[k
]
966 other_nets
[k
]['external']=False
969 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
970 for name
,vnf
in vnfs
.items():
972 where_or
={"tenant_id": tenant_id
, 'public': "true"}
974 error_pos
= "'topology':'nodes':'" + name
+ "'"
976 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
977 where
['uuid'] = vnf
['vnf_id']
978 if 'VNF model' in vnf
:
979 error_text
+= " 'VNF model' " + vnf
['VNF model']
980 where
['name'] = vnf
['VNF model']
982 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
984 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
990 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
992 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
993 vnf
['uuid']=vnf_db
[0]['uuid']
994 vnf
['description']=vnf_db
[0]['description']
995 #get external interfaces
996 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
997 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
998 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
999 for ext_iface
in ext_ifaces
:
1000 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1002 #1.4 get list of connections
1003 conections
= topo
['topology']['connections']
1004 conections_list
= []
1005 conections_list_name
= []
1006 for k
in conections
.keys():
1007 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1008 ifaces_list
= conections
[k
]['nodes'].items()
1009 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1011 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1012 for k2
in conection_pair_list
:
1015 con_type
= conections
[k
].get("type", "link")
1016 if con_type
!= "link":
1018 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1019 other_nets
[k
] = {'external': False}
1020 if conections
[k
].get("graph"):
1021 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1022 ifaces_list
.append( (k
, None) )
1025 if con_type
== "external_network":
1026 other_nets
[k
]['external'] = True
1027 if conections
[k
].get("model"):
1028 other_nets
[k
]["model"] = conections
[k
]["model"]
1030 other_nets
[k
]["model"] = k
1031 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1032 other_nets
[k
]["model"] = con_type
1034 conections_list_name
.append(k
)
1035 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)
1036 #print set(ifaces_list)
1037 #check valid VNF and iface names
1038 for iface
in ifaces_list
:
1039 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1040 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1041 str(k
), iface
[0]), HTTP_Not_Found
)
1042 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1043 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1044 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1046 #1.5 unify connections from the pair list to a consolidated list
1048 while index
< len(conections_list
):
1050 while index2
< len(conections_list
):
1051 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1052 conections_list
[index
] |
= conections_list
[index2
]
1053 del conections_list
[index2
]
1054 del conections_list_name
[index2
]
1057 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1059 #for k in conections_list:
1064 #1.6 Delete non external nets
1065 # for k in other_nets.keys():
1066 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1067 # for con in conections_list:
1069 # for index in range(0,len(con)):
1070 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1071 # for index in delete_indexes:
1074 #1.7: Check external_ports are present at database table datacenter_nets
1075 for k
,net
in other_nets
.items():
1076 error_pos
= "'topology':'nodes':'" + k
+ "'"
1077 if net
['external']==False:
1078 if 'name' not in net
:
1080 if 'model' not in net
:
1081 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1082 if net
['model']=='bridge_net':
1083 net
['type']='bridge';
1084 elif net
['model']=='dataplane_net':
1087 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1089 #IF we do not want to check that external network exist at datacenter
1094 # if 'net_id' in net:
1095 # error_text += " 'net_id' " + net['net_id']
1096 # WHERE_['uuid'] = net['net_id']
1097 # if 'model' in net:
1098 # error_text += " 'model' " + net['model']
1099 # WHERE_['name'] = net['model']
1100 # if len(WHERE_) == 0:
1101 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1102 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1103 # FROM='datacenter_nets', WHERE=WHERE_ )
1105 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1107 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1108 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1110 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1111 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1112 # other_nets[k].update(net_db[0])
1115 net_nb
=0 #Number of nets
1116 for con
in conections_list
:
1117 #check if this is connected to a external net
1121 for index
in range(0,len(con
)):
1122 #check if this is connected to a external net
1123 for net_key
in other_nets
.keys():
1124 if con
[index
][0]==net_key
:
1125 if other_net_index
>=0:
1126 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1127 #print "nfvo.new_scenario " + error_text
1128 raise NfvoException(error_text
, HTTP_Bad_Request
)
1130 other_net_index
= index
1131 net_target
= net_key
1133 #print "other_net_index", other_net_index
1135 if other_net_index
>=0:
1136 del con
[other_net_index
]
1137 #IF we do not want to check that external network exist at datacenter
1138 if other_nets
[net_target
]['external'] :
1139 if "name" not in other_nets
[net_target
]:
1140 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1141 if other_nets
[net_target
]["type"] == "external_network":
1142 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1143 other_nets
[net_target
]["type"] = "data"
1145 other_nets
[net_target
]["type"] = "bridge"
1147 # if other_nets[net_target]['external'] :
1148 # 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
1149 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1150 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1151 # print "nfvo.new_scenario " + error_text
1152 # return -HTTP_Bad_Request, error_text
1155 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1158 net_type_bridge
=False
1160 net_target
= "__-__net"+str(net_nb
)
1161 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1162 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1165 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1166 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1167 if iface_type
=='mgmt' or iface_type
=='bridge':
1168 net_type_bridge
= True
1170 net_type_data
= True
1171 if net_type_bridge
and net_type_data
:
1172 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1173 #print "nfvo.new_scenario " + error_text
1174 raise NfvoException(error_text
, HTTP_Bad_Request
)
1175 elif net_type_bridge
:
1178 type_
='data' if len(con
)>2 else 'ptp'
1179 net_list
[net_target
]['type'] = type_
1182 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1183 #print "nfvo.new_scenario " + error_text
1185 raise NfvoException(error_text
, HTTP_Bad_Request
)
1187 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1188 #1.8.1 obtain management net
1189 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1190 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1191 #1.8.2 check all interfaces from all vnfs
1193 add_mgmt_net
= False
1194 for vnf
in vnfs
.values():
1195 for iface
in vnf
['ifaces'].values():
1196 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1197 #iface not connected
1198 iface
['net_key'] = 'mgmt'
1200 if add_mgmt_net
and 'mgmt' not in net_list
:
1201 net_list
['mgmt']=mgmt_net
[0]
1202 net_list
['mgmt']['external']=True
1203 net_list
['mgmt']['graph']={'visible':False}
1205 net_list
.update(other_nets
)
1207 #print 'net_list', net_list
1212 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1213 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1214 'tenant_id':tenant_id
, 'name':topo
['name'],
1215 'description':topo
.get('description',topo
['name']),
1216 'public': topo
.get('public', False)
1221 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
):
1222 scenario
= scenario_dict
["scenario"]
1223 if tenant_id
!= "any":
1224 check_tenant(mydb
, tenant_id
)
1225 if "tenant_id" in scenario
:
1226 if scenario
["tenant_id"] != tenant_id
:
1227 print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1228 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1229 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1233 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1234 for name
,vnf
in scenario
["vnfs"].iteritems():
1236 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1238 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1240 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1241 where
['uuid'] = vnf
['vnf_id']
1242 if 'vnf_name' in vnf
:
1243 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1244 where
['name'] = vnf
['vnf_name']
1246 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1247 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1253 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1255 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1256 vnf
['uuid']=vnf_db
[0]['uuid']
1257 vnf
['description']=vnf_db
[0]['description']
1259 #get external interfaces
1260 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1261 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1262 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1263 for ext_iface
in ext_ifaces
:
1264 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1266 #2: Insert net_key at every vnf interface
1267 for net_name
,net
in scenario
["networks"].iteritems():
1268 net_type_bridge
=False
1270 for iface_dict
in net
["interfaces"]:
1271 for vnf
,iface
in iface_dict
.iteritems():
1272 if vnf
not in scenario
["vnfs"]:
1273 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1274 #print "nfvo.new_scenario_v02 " + error_text
1275 raise NfvoException(error_text
, HTTP_Not_Found
)
1276 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1277 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1278 #print "nfvo.new_scenario_v02 " + error_text
1279 raise NfvoException(error_text
, HTTP_Bad_Request
)
1280 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1281 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1282 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1283 #print "nfvo.new_scenario_v02 " + error_text
1284 raise NfvoException(error_text
, HTTP_Bad_Request
)
1285 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1286 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1287 if iface_type
=='mgmt' or iface_type
=='bridge':
1288 net_type_bridge
= True
1290 net_type_data
= True
1291 if net_type_bridge
and net_type_data
:
1292 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1293 #print "nfvo.new_scenario " + error_text
1294 raise NfvoException(error_text
, HTTP_Bad_Request
)
1295 elif net_type_bridge
:
1298 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1300 net
['name'] = net_name
1301 net
['external'] = net
.get('external', False)
1303 #3: insert at database
1304 scenario
["nets"] = scenario
["networks"]
1305 scenario
['tenant_id'] = tenant_id
1306 scenario_id
= mydb
.new_scenario( scenario
)
1309 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1310 data
["uuid"] = scenario_id
1311 data
["tenant_id"] = tenant_id
1312 c
= mydb
.edit_scenario( data
)
1315 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1316 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1317 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
1318 vims
= {datacenter_id
: myvim
}
1319 myvim_tenant
= myvim
['tenant_id']
1320 datacenter_name
= myvim
['name']
1324 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1325 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1326 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
1327 scenarioDict
['datacenter_id'] = datacenter_id
1328 #print '================scenarioDict======================='
1329 #print json.dumps(scenarioDict, indent=4)
1330 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1332 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1333 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1335 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1336 auxNetDict
['scenario'] = {}
1338 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1339 for sce_net
in scenarioDict
['nets']:
1340 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1342 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1343 myNetName
= myNetName
[0:255] #limit length
1344 myNetType
= sce_net
['type']
1346 myNetDict
["name"] = myNetName
1347 myNetDict
["type"] = myNetType
1348 myNetDict
["tenant_id"] = myvim_tenant
1349 myNetIPProfile
= sce_net
.get('ip_profile', None)
1351 #We should use the dictionary as input parameter for new_network
1353 if not sce_net
["external"]:
1354 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1355 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1356 sce_net
['vim_id'] = network_id
1357 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1358 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1359 sce_net
["created"] = True
1361 if sce_net
['vim_id'] == None:
1362 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1363 _
, message
= rollback(mydb
, vims
, rollbackList
)
1364 logger
.error("nfvo.start_scenario: %s", error_text
)
1365 raise NfvoException(error_text
, HTTP_Bad_Request
)
1366 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1367 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1369 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1370 #For each vnf net, we create it and we add it to instanceNetlist.
1371 for sce_vnf
in scenarioDict
['vnfs']:
1372 for net
in sce_vnf
['nets']:
1373 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1375 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1376 myNetName
= myNetName
[0:255] #limit length
1377 myNetType
= net
['type']
1379 myNetDict
["name"] = myNetName
1380 myNetDict
["type"] = myNetType
1381 myNetDict
["tenant_id"] = myvim_tenant
1382 myNetIPProfile
= net
.get('ip_profile', None)
1385 #We should use the dictionary as input parameter for new_network
1386 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1387 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1388 net
['vim_id'] = network_id
1389 if sce_vnf
['uuid'] not in auxNetDict
:
1390 auxNetDict
[sce_vnf
['uuid']] = {}
1391 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1392 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1393 net
["created"] = True
1395 #print "auxNetDict:"
1396 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1398 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1399 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1401 for sce_vnf
in scenarioDict
['vnfs']:
1402 for vm
in sce_vnf
['vms']:
1405 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1406 myVMDict
['name'] = "%s.%s.%d" % (instance_scenario_name
,sce_vnf
['name'],i
)
1407 #myVMDict['description'] = vm['description']
1408 myVMDict
['description'] = myVMDict
['name'][0:99]
1410 myVMDict
['start'] = "no"
1411 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1412 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1414 #create image at vim in case it not exist
1415 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1416 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1417 vm
['vim_image_id'] = image_id
1419 #create flavor at vim in case it not exist
1420 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1421 if flavor_dict
['extended']!=None:
1422 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1423 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1424 vm
['vim_flavor_id'] = flavor_id
1427 myVMDict
['imageRef'] = vm
['vim_image_id']
1428 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1429 myVMDict
['networks'] = []
1430 for iface
in vm
['interfaces']:
1432 if iface
['type']=="data":
1433 netDict
['type'] = iface
['model']
1434 elif "model" in iface
and iface
["model"]!=None:
1435 netDict
['model']=iface
['model']
1436 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1437 #discover type of interface looking at flavor
1438 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1439 for flavor_iface
in numa
.get('interfaces',[]):
1440 if flavor_iface
.get('name') == iface
['internal_name']:
1441 if flavor_iface
['dedicated'] == 'yes':
1442 netDict
['type']="PF" #passthrough
1443 elif flavor_iface
['dedicated'] == 'no':
1444 netDict
['type']="VF" #siov
1445 elif flavor_iface
['dedicated'] == 'yes:sriov':
1446 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1447 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1449 netDict
["use"]=iface
['type']
1450 if netDict
["use"]=="data" and not netDict
.get("type"):
1451 #print "netDict", netDict
1452 #print "iface", iface
1453 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'])
1454 if flavor_dict
.get('extended')==None:
1455 raise NfvoException(e_text
+ "After database migration some information is not available. \
1456 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1458 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1459 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1460 netDict
["type"]="virtual"
1461 if "vpci" in iface
and iface
["vpci"] is not None:
1462 netDict
['vpci'] = iface
['vpci']
1463 if "mac" in iface
and iface
["mac"] is not None:
1464 netDict
['mac_address'] = iface
['mac']
1465 netDict
['name'] = iface
['internal_name']
1466 if iface
['net_id'] is None:
1467 for vnf_iface
in sce_vnf
["interfaces"]:
1470 if vnf_iface
['interface_id']==iface
['uuid']:
1471 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1474 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1475 #skip bridge ifaces not connected to any net
1476 #if 'net_id' not in netDict or netDict['net_id']==None:
1478 myVMDict
['networks'].append(netDict
)
1479 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1480 #print myVMDict['name']
1481 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1482 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1483 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1484 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1485 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1486 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1487 vm
['vim_id'] = vm_id
1488 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1489 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1490 for net
in myVMDict
['networks']:
1492 for iface
in vm
['interfaces']:
1493 if net
["name"]==iface
["internal_name"]:
1494 iface
["vim_id"]=net
["vim_id"]
1497 logger
.debug("start scenario Deployment done")
1498 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1499 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1500 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1501 return mydb
.get_instance_scenario(instance_id
)
1503 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1504 _
, message
= rollback(mydb
, vims
, rollbackList
)
1505 if isinstance(e
, db_base_Exception
):
1506 error_text
= "Exception at database"
1508 error_text
= "Exception at VIM"
1509 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1510 #logger.error("start_scenario %s", error_text)
1511 raise NfvoException(error_text
, e
.http_code
)
1513 def unify_cloud_config(cloud_config
):
1514 index_to_delete
= []
1515 users
= cloud_config
.get("users", [])
1516 for index0
in range(0,len(users
)):
1517 if index0
in index_to_delete
:
1519 for index1
in range(index0
+1,len(users
)):
1520 if index1
in index_to_delete
:
1522 if users
[index0
]["name"] == users
[index1
]["name"]:
1523 index_to_delete
.append(index1
)
1524 for key
in users
[index1
].get("key-pairs",()):
1525 if "key-pairs" not in users
[index0
]:
1526 users
[index0
]["key-pairs"] = [key
]
1527 elif key
not in users
[index0
]["key-pairs"]:
1528 users
[index0
]["key-pairs"].append(key
)
1529 index_to_delete
.sort(reverse
=True)
1530 for index
in index_to_delete
:
1533 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1534 datacenter_id
= None
1535 datacenter_name
= None
1536 if datacenter_id_name
:
1537 if utils
.check_valid_uuid(datacenter_id_name
):
1538 datacenter_id
= datacenter_id_name
1540 datacenter_name
= datacenter_id_name
1541 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1543 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1545 #print "nfvo.datacenter_action() error. Several datacenters found"
1546 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1547 return vims
.keys()[0], vims
.values()[0]
1549 def new_scenario_v03(mydb
, tenant_id
, scenario_dict
):
1550 scenario
= scenario_dict
["scenario"]
1551 if tenant_id
!= "any":
1552 check_tenant(mydb
, tenant_id
)
1553 if "tenant_id" in scenario
:
1554 if scenario
["tenant_id"] != tenant_id
:
1555 logger("Tenant '%s' not found", tenant_id
)
1556 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1557 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1561 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1562 for name
,vnf
in scenario
["vnfs"].iteritems():
1564 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1566 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1568 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1569 where
['uuid'] = vnf
['vnf_id']
1570 if 'vnf_name' in vnf
:
1571 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1572 where
['name'] = vnf
['vnf_name']
1574 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1575 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1581 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1583 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1584 vnf
['uuid']=vnf_db
[0]['uuid']
1585 vnf
['description']=vnf_db
[0]['description']
1587 # get external interfaces
1588 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1589 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1590 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1591 for ext_iface
in ext_ifaces
:
1592 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1594 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1596 #2: Insert net_key and ip_address at every vnf interface
1597 for net_name
,net
in scenario
["networks"].iteritems():
1598 net_type_bridge
=False
1600 for iface_dict
in net
["interfaces"]:
1601 logger
.debug("Iface_dict %s", iface_dict
)
1602 vnf
= iface_dict
["vnf"]
1603 iface
= iface_dict
["vnf_interface"]
1604 if vnf
not in scenario
["vnfs"]:
1605 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1606 #logger.debug(error_text)
1607 raise NfvoException(error_text
, HTTP_Not_Found
)
1608 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1609 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1610 #logger.debug(error_text)
1611 raise NfvoException(error_text
, HTTP_Bad_Request
)
1612 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1613 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1614 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1615 #logger.debug(error_text)
1616 raise NfvoException(error_text
, HTTP_Bad_Request
)
1617 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1618 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['ip_address'] = iface_dict
.get('ip_address',None)
1619 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1620 if iface_type
=='mgmt' or iface_type
=='bridge':
1621 net_type_bridge
= True
1623 net_type_data
= True
1624 if net_type_bridge
and net_type_data
:
1625 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1626 #logger.debug(error_text)
1627 raise NfvoException(error_text
, HTTP_Bad_Request
)
1628 elif net_type_bridge
:
1631 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1633 if ("implementation" in net
):
1634 if (type_
== "bridge" and net
["implementation"] == "underlay"):
1635 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at 'network':'%s'" % (net_name
)
1636 #logger.debug(error_text)
1637 raise NfvoException(error_text
, HTTP_Bad_Request
)
1638 elif (type_
<> "bridge" and net
["implementation"] == "overlay"):
1639 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at 'network':'%s'" % (net_name
)
1640 #logger.debug(error_text)
1641 raise NfvoException(error_text
, HTTP_Bad_Request
)
1642 net
.pop("implementation")
1644 if (type_
== "data" and net
["type"] == "e-line"):
1645 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type 'e-line' at 'network':'%s'" % (net_name
)
1646 #logger.debug(error_text)
1647 raise NfvoException(error_text
, HTTP_Bad_Request
)
1648 elif (type_
== "ptp" and net
["type"] == "e-lan"):
1652 net
['name'] = net_name
1653 net
['external'] = net
.get('external', False)
1655 #3: insert at database
1656 scenario
["nets"] = scenario
["networks"]
1657 scenario
['tenant_id'] = tenant_id
1658 scenario_id
= mydb
.new_scenario2(scenario
)
1662 '''Takes dict d and updates it with the values in dict u.'''
1663 '''It merges all depth levels'''
1664 for k
, v
in u
.iteritems():
1665 if isinstance(v
, collections
.Mapping
):
1666 r
= update(d
.get(k
, {}), v
)
1672 def create_instance(mydb
, tenant_id
, instance_dict
):
1673 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1674 #logger.debug("Creating instance...")
1675 scenario
= instance_dict
["scenario"]
1677 #find main datacenter
1679 datacenter2tenant
= {}
1680 datacenter
= instance_dict
.get("datacenter")
1681 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1682 myvims
[default_datacenter_id
] = vim
1683 datacenter2tenant
[default_datacenter_id
] = vim
['config']['datacenter_tenant_id']
1684 #myvim_tenant = myvim['tenant_id']
1685 # default_datacenter_name = vim['name']
1688 #print "Checking that the scenario exists and getting the scenario dictionary"
1689 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1691 #logger.debug(">>>>>>> Dictionaries before merging")
1692 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1693 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1695 scenarioDict
['datacenter_id'] = default_datacenter_id
1697 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1698 auxNetDict
['scenario'] = {}
1700 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1701 instance_name
= instance_dict
["name"]
1702 instance_description
= instance_dict
.get("description")
1704 #0 check correct parameters
1705 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1707 for scenario_net
in scenarioDict
['nets']:
1708 if net_name
== scenario_net
["name"]:
1712 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1713 if "sites" not in net_instance_desc
:
1714 net_instance_desc
["sites"] = [ {} ]
1715 site_without_datacenter_field
= False
1716 for site
in net_instance_desc
["sites"]:
1717 if site
.get("datacenter"):
1718 if site
["datacenter"] not in myvims
:
1719 #Add this datacenter to myvims
1720 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1722 datacenter2tenant
[d
] = v
['config']['datacenter_tenant_id']
1723 site
["datacenter"] = d
#change name to id
1725 if site_without_datacenter_field
:
1726 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1727 site_without_datacenter_field
= True
1728 site
["datacenter"] = default_datacenter_id
#change name to id
1730 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
1732 for scenario_vnf
in scenarioDict
['vnfs']:
1733 if vnf_name
== scenario_vnf
['name']:
1737 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
1738 if "datacenter" in vnf_instance_desc
:
1739 #Add this datacenter to myvims
1740 if vnf_instance_desc
["datacenter"] not in myvims
:
1741 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
1743 datacenter2tenant
[d
] = v
['config']['datacenter_tenant_id']
1744 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
1745 #0.1 parse cloud-config parameters
1746 cloud_config
= scenarioDict
.get("cloud-config", {})
1747 if instance_dict
.get("cloud-config"):
1748 cloud_config
.update( instance_dict
["cloud-config"])
1749 if not cloud_config
:
1752 scenarioDict
["cloud-config"] = cloud_config
1753 unify_cloud_config(cloud_config
)
1755 #0.2 merge instance information into scenario
1756 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
1757 #However, this is not possible yet.
1758 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1759 for scenario_net
in scenarioDict
['nets']:
1760 if net_name
== scenario_net
["name"]:
1761 if 'ip-profile' in net_instance_desc
:
1762 ipprofile
= net_instance_desc
['ip-profile']
1763 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
1764 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
1765 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
1766 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
1767 if 'dhcp' in ipprofile
:
1768 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
1769 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
1770 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
1771 del ipprofile
['dhcp']
1772 if 'ip_profile' not in scenario_net
:
1773 scenario_net
['ip_profile'] = ipprofile
1775 update(scenario_net
['ip_profile'],ipprofile
)
1776 for interface
in net_instance_desc
.get('interfaces', () ):
1777 if 'ip_address' in interface
:
1778 for vnf
in scenarioDict
['vnfs']:
1779 if interface
['vnf'] == vnf
['name']:
1780 for vnf_interface
in vnf
['interfaces']:
1781 if interface
['vnf_interface'] == vnf_interface
['external_name']:
1782 vnf_interface
['ip_address']=interface
['ip_address']
1784 #logger.debug(">>>>>>>> Merged dictionary")
1785 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
1788 #1. Creating new nets (sce_nets) in the VIM"
1789 for sce_net
in scenarioDict
['nets']:
1790 sce_net
["vim_id_sites"]={}
1791 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
1792 net_name
= descriptor_net
.get("vim-network-name")
1793 auxNetDict
['scenario'][sce_net
['uuid']] = {}
1795 sites
= descriptor_net
.get("sites", [ {} ])
1797 if site
.get("datacenter"):
1798 vim
= myvims
[ site
["datacenter"] ]
1799 datacenter_id
= site
["datacenter"]
1801 vim
= myvims
[ default_datacenter_id
]
1802 datacenter_id
= default_datacenter_id
1803 net_type
= sce_net
['type']
1804 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
1805 if sce_net
["external"]:
1807 net_name
= sce_net
["name"]
1808 if "netmap-use" in site
or "netmap-create" in site
:
1809 create_network
= False
1810 lookfor_network
= False
1811 if "netmap-use" in site
:
1812 lookfor_network
= True
1813 if utils
.check_valid_uuid(site
["netmap-use"]):
1814 filter_text
= "scenario id '%s'" % site
["netmap-use"]
1815 lookfor_filter
["id"] = site
["netmap-use"]
1817 filter_text
= "scenario name '%s'" % site
["netmap-use"]
1818 lookfor_filter
["name"] = site
["netmap-use"]
1819 if "netmap-create" in site
:
1820 create_network
= True
1821 net_vim_name
= net_name
1822 if site
["netmap-create"]:
1823 net_vim_name
= site
["netmap-create"]
1825 elif sce_net
['vim_id'] != None:
1826 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
1827 create_network
= False
1828 lookfor_network
= True
1829 lookfor_filter
["id"] = sce_net
['vim_id']
1830 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
1831 #look for network at datacenter and return error
1833 #There is not a netmap, look at datacenter for a net with this name and create if not found
1834 create_network
= True
1835 lookfor_network
= True
1836 lookfor_filter
["name"] = sce_net
["name"]
1837 net_vim_name
= sce_net
["name"]
1838 filter_text
= "scenario name '%s'" % sce_net
["name"]
1841 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
1842 net_name
= net_name
[:255] #limit length
1843 net_vim_name
= net_name
1844 create_network
= True
1845 lookfor_network
= False
1848 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
1849 if len(vim_nets
) > 1:
1850 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1851 elif len(vim_nets
) == 0:
1852 if not create_network
:
1853 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1855 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
1856 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
1857 create_network
= False
1859 #if network is not external
1860 network_id
= vim
.new_network(net_vim_name
, net_type
, sce_net
.get('ip_profile',None))
1861 sce_net
["vim_id_sites"][datacenter_id
] = network_id
1862 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = network_id
1863 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':network_id
})
1864 sce_net
["created"] = True
1866 #2. Creating new nets (vnf internal nets) in the VIM"
1867 #For each vnf net, we create it and we add it to instanceNetlist.
1868 for sce_vnf
in scenarioDict
['vnfs']:
1869 for net
in sce_vnf
['nets']:
1870 if sce_vnf
.get("datacenter"):
1871 vim
= myvims
[ sce_vnf
["datacenter"] ]
1872 datacenter_id
= sce_vnf
["datacenter"]
1874 vim
= myvims
[ default_datacenter_id
]
1875 datacenter_id
= default_datacenter_id
1876 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
1877 net_name
= descriptor_net
.get("name")
1879 net_name
= "%s.%s" %(instance_name
, net
["name"])
1880 net_name
= net_name
[:255] #limit length
1881 net_type
= net
['type']
1882 network_id
= vim
.new_network(net_name
, net_type
, net
.get('ip_profile',None))
1883 net
['vim_id'] = network_id
1884 if sce_vnf
['uuid'] not in auxNetDict
:
1885 auxNetDict
[sce_vnf
['uuid']] = {}
1886 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1887 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1888 net
["created"] = True
1891 #print "auxNetDict:"
1892 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1894 #3. Creating new vm instances in the VIM
1895 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1896 for sce_vnf
in scenarioDict
['vnfs']:
1897 if sce_vnf
.get("datacenter"):
1898 vim
= myvims
[ sce_vnf
["datacenter"] ]
1899 datacenter_id
= sce_vnf
["datacenter"]
1901 vim
= myvims
[ default_datacenter_id
]
1902 datacenter_id
= default_datacenter_id
1903 sce_vnf
["datacenter_id"] = datacenter_id
1905 for vm
in sce_vnf
['vms']:
1908 myVMDict
['name'] = "%s.%s.%d" % (instance_name
,sce_vnf
['name'],i
)
1909 myVMDict
['description'] = myVMDict
['name'][0:99]
1911 # myVMDict['start'] = "no"
1912 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1913 #create image at vim in case it not exist
1914 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1915 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
1916 vm
['vim_image_id'] = image_id
1918 #create flavor at vim in case it not exist
1919 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1920 if flavor_dict
['extended']!=None:
1921 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1922 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
1923 vm
['vim_flavor_id'] = flavor_id
1925 myVMDict
['imageRef'] = vm
['vim_image_id']
1926 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1927 myVMDict
['networks'] = []
1928 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
1929 for iface
in vm
['interfaces']:
1931 if iface
['type']=="data":
1932 netDict
['type'] = iface
['model']
1933 elif "model" in iface
and iface
["model"]!=None:
1934 netDict
['model']=iface
['model']
1935 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1936 #discover type of interface looking at flavor
1937 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1938 for flavor_iface
in numa
.get('interfaces',[]):
1939 if flavor_iface
.get('name') == iface
['internal_name']:
1940 if flavor_iface
['dedicated'] == 'yes':
1941 netDict
['type']="PF" #passthrough
1942 elif flavor_iface
['dedicated'] == 'no':
1943 netDict
['type']="VF" #siov
1944 elif flavor_iface
['dedicated'] == 'yes:sriov':
1945 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1946 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1948 netDict
["use"]=iface
['type']
1949 if netDict
["use"]=="data" and not netDict
.get("type"):
1950 #print "netDict", netDict
1951 #print "iface", iface
1952 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'])
1953 if flavor_dict
.get('extended')==None:
1954 raise NfvoException(e_text
+ "After database migration some information is not available. \
1955 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1957 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1958 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1959 netDict
["type"]="virtual"
1960 if "vpci" in iface
and iface
["vpci"] is not None:
1961 netDict
['vpci'] = iface
['vpci']
1962 if "mac" in iface
and iface
["mac"] is not None:
1963 netDict
['mac_address'] = iface
['mac']
1964 netDict
['name'] = iface
['internal_name']
1965 if iface
['net_id'] is None:
1966 for vnf_iface
in sce_vnf
["interfaces"]:
1969 if vnf_iface
['interface_id']==iface
['uuid']:
1970 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
1973 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1974 #skip bridge ifaces not connected to any net
1975 #if 'net_id' not in netDict or netDict['net_id']==None:
1977 myVMDict
['networks'].append(netDict
)
1978 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1979 #print myVMDict['name']
1980 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1981 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1982 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1983 vm_id
= vim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1984 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'], cloud_config
= cloud_config
)
1985 vm
['vim_id'] = vm_id
1986 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1987 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1988 for net
in myVMDict
['networks']:
1990 for iface
in vm
['interfaces']:
1991 if net
["name"]==iface
["internal_name"]:
1992 iface
["vim_id"]=net
["vim_id"]
1994 scenarioDict
["datacenter2tenant"] = datacenter2tenant
1995 logger
.debug("create_instance Deployment done scenarioDict: %s",
1996 yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False) )
1997 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
1998 return mydb
.get_instance_scenario(instance_id
)
1999 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2000 message
= rollback(mydb
, myvims
, rollbackList
)
2001 if isinstance(e
, db_base_Exception
):
2002 error_text
= "database Exception"
2003 elif isinstance(e
, vimconn
.vimconnException
):
2004 error_text
= "VIM Exception"
2006 error_text
= "Exception"
2007 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2008 #logger.error("create_instance: %s", error_text)
2009 raise NfvoException(error_text
, e
.http_code
)
2011 def delete_instance(mydb
, tenant_id
, instance_id
):
2012 #print "Checking that the instance_id exists and getting the instance dictionary"
2013 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2014 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2015 tenant_id
= instanceDict
["tenant_id"]
2016 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2018 #1. Delete from Database
2019 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2027 for sce_vnf
in instanceDict
['vnfs']:
2028 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2029 if datacenter_key
not in myvims
:
2030 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2031 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2033 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2034 sce_vnf
["datacenter_tenant_id"]))
2035 myvims
[datacenter_key
] = None
2037 myvims
[datacenter_key
] = vims
.values()[0]
2038 myvim
= myvims
[datacenter_key
]
2039 for vm
in sce_vnf
['vms']:
2041 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2044 myvim
.delete_vminstance(vm
['vim_vm_id'])
2045 except vimconn
.vimconnNotFoundException
as e
:
2046 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2047 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2048 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2049 except vimconn
.vimconnException
as e
:
2050 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2051 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2052 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2056 for net
in instanceDict
['nets']:
2057 if not net
['created']:
2058 continue #skip not created nets
2059 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2060 if datacenter_key
not in myvims
:
2061 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2062 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2064 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2065 myvims
[datacenter_key
] = None
2067 myvims
[datacenter_key
] = vims
.values()[0]
2068 myvim
= myvims
[datacenter_key
]
2071 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2074 myvim
.delete_network(net
['vim_net_id'])
2075 except vimconn
.vimconnNotFoundException
as e
:
2076 error_msg
+="\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2077 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2078 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2079 except vimconn
.vimconnException
as e
:
2080 error_msg
+="\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'], net
["datacenter_id"], e
.http_code
, str(e
))
2081 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2082 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2083 if len(error_msg
)>0:
2084 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2086 return 'instance ' + message
+ ' deleted'
2088 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2089 '''Refreshes a scenario instance. It modifies instanceDict'''
2091 - 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
2094 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2095 #print "nfvo.refresh_instance begins"
2096 #print json.dumps(instanceDict, indent=4)
2098 #print "Getting the VIM URL and the VIM tenant_id"
2101 # 1. Getting VIM vm and net list
2102 vms_updated
= [] #List of VM instance uuids in openmano that were updated
2105 for sce_vnf
in instanceDict
['vnfs']:
2106 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2107 if datacenter_key
not in vm_list
:
2108 vm_list
[datacenter_key
] = []
2109 if datacenter_key
not in myvims
:
2110 vims
= get_vim(mydb
, nfvo_tenant
, datacenter_id
=sce_vnf
["datacenter_id"],
2111 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2113 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"]))
2114 myvims
[datacenter_key
] = None
2116 myvims
[datacenter_key
] = vims
.values()[0]
2117 for vm
in sce_vnf
['vms']:
2118 vm_list
[datacenter_key
].append(vm
['vim_vm_id'])
2119 vms_notupdated
.append(vm
["uuid"])
2121 nets_updated
= [] #List of VM instance uuids in openmano that were updated
2124 for net
in instanceDict
['nets']:
2125 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2126 if datacenter_key
not in net_list
:
2127 net_list
[datacenter_key
] = []
2128 if datacenter_key
not in myvims
:
2129 vims
= get_vim(mydb
, nfvo_tenant
, datacenter_id
=net
["datacenter_id"],
2130 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2132 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2133 myvims
[datacenter_key
] = None
2135 myvims
[datacenter_key
] = vims
.values()[0]
2137 net_list
[datacenter_key
].append(net
['vim_net_id'])
2138 nets_notupdated
.append(net
["uuid"])
2140 # 1. Getting the status of all VMs
2142 for datacenter_key
in myvims
:
2143 if not vm_list
.get(datacenter_key
):
2147 if not myvims
[datacenter_key
]:
2148 failed_message
= "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"])
2151 vm_dict
.update(myvims
[datacenter_key
].refresh_vms_status(vm_list
[datacenter_key
]) )
2153 except vimconn
.vimconnException
as e
:
2154 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
2155 failed_message
= str(e
)
2157 for vm
in vm_list
[datacenter_key
]:
2158 vm_dict
[vm
] = {'status': "VIM_ERROR", 'error_msg': failed_message
}
2160 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2161 for sce_vnf
in instanceDict
['vnfs']:
2162 for vm
in sce_vnf
['vms']:
2163 vm_id
= vm
['vim_vm_id']
2164 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
2165 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2166 has_mgmt_iface
= False
2167 for iface
in vm
["interfaces"]:
2168 if iface
["type"]=="mgmt":
2169 has_mgmt_iface
= True
2170 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
2171 vm_dict
[vm_id
]['status'] = "ACTIVE"
2172 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'):
2173 vm
['status'] = vm_dict
[vm_id
]['status']
2174 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
2175 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
2176 # 2.1. Update in openmano DB the VMs whose status changed
2178 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
2179 vms_notupdated
.remove(vm
["uuid"])
2181 vms_updated
.append(vm
["uuid"])
2182 except db_base_Exception
as e
:
2183 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2184 # 2.2. Update in openmano DB the interface VMs
2185 for interface
in interfaces
:
2186 #translate from vim_net_id to instance_net_id
2188 for net
in instanceDict
['nets']:
2189 if net
["vim_net_id"] == interface
["vim_net_id"]:
2190 network_id_list
.append(net
["uuid"])
2191 if not network_id_list
:
2193 del interface
["vim_net_id"]
2195 for network_id
in network_id_list
:
2196 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
2197 except db_base_Exception
as e
:
2198 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
2200 # 3. Getting the status of all nets
2202 for datacenter_key
in myvims
:
2203 if not net_list
.get(datacenter_key
):
2207 if not myvims
[datacenter_key
]:
2208 failed_message
= "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"])
2211 net_dict
.update(myvims
[datacenter_key
].refresh_nets_status(net_list
[datacenter_key
]) )
2213 except vimconn
.vimconnException
as e
:
2214 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
2215 failed_message
= str(e
)
2217 for net
in net_list
[datacenter_key
]:
2218 net_dict
[net
] = {'status': "VIM_ERROR", 'error_msg': failed_message
}
2220 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2221 # TODO: update nets inside a vnf
2222 for net
in instanceDict
['nets']:
2223 net_id
= net
['vim_net_id']
2224 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'):
2225 net
['status'] = net_dict
[net_id
]['status']
2226 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
2227 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
2228 # 5.1. Update in openmano DB the nets whose status changed
2230 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
2231 nets_notupdated
.remove(net
["uuid"])
2233 nets_updated
.append(net
["uuid"])
2234 except db_base_Exception
as e
:
2235 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2237 # Returns appropriate output
2238 #print "nfvo.refresh_instance finishes"
2239 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2240 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
2241 instance_id
= instanceDict
['uuid']
2242 if len(vms_notupdated
)+len(nets_notupdated
)>0:
2243 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
2244 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
2246 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2248 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2249 #print "Checking that the instance_id exists and getting the instance dictionary"
2250 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2251 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2253 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2254 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2256 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2257 myvim
= vims
.values()[0]
2260 input_vnfs
= action_dict
.pop("vnfs", [])
2261 input_vms
= action_dict
.pop("vms", [])
2262 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2266 for sce_vnf
in instanceDict
['vnfs']:
2267 for vm
in sce_vnf
['vms']:
2268 if not action_over_all
:
2269 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2270 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2273 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2274 if "console" in action_dict
:
2275 if not global_config
["http_console_proxy"]:
2276 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2277 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2278 protocol
=data
["protocol"],
2279 ip
= data
["server"],
2280 port
= data
["port"],
2281 suffix
= data
["suffix"]),
2285 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2286 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2287 "description": "this console is only reachable by local interface",
2292 #print "console data", data
2294 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2295 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2296 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2297 protocol
=data
["protocol"],
2298 ip
= global_config
["http_console_host"],
2299 port
= console_thread
.port
,
2300 suffix
= data
["suffix"]),
2304 except NfvoException
as e
:
2305 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2309 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2311 except vimconn
.vimconnException
as e
:
2312 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2315 if vm_ok
==0: #all goes wrong
2320 def create_or_use_console_proxy_thread(console_server
, console_port
):
2321 #look for a non-used port
2322 console_thread_key
= console_server
+ ":" + str(console_port
)
2323 if console_thread_key
in global_config
["console_thread"]:
2324 #global_config["console_thread"][console_thread_key].start_timeout()
2325 return global_config
["console_thread"][console_thread_key
]
2327 for port
in global_config
["console_port_iterator"]():
2328 #print "create_or_use_console_proxy_thread() port:", port
2329 if port
in global_config
["console_ports"]:
2332 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2334 global_config
["console_thread"][console_thread_key
] = clithread
2335 global_config
["console_ports"][port
] = console_thread_key
2337 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2338 #port used, try with onoher
2340 except cli
.ConsoleProxyException
as e
:
2341 raise NfvoException(str(e
), HTTP_Bad_Request
)
2342 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2344 def check_tenant(mydb
, tenant_id
):
2345 '''check that tenant exists at database'''
2346 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2348 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2351 def new_tenant(mydb
, tenant_dict
):
2352 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2355 def delete_tenant(mydb
, tenant
):
2356 #get nfvo_tenant info
2358 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2359 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2360 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2362 def new_datacenter(mydb
, datacenter_descriptor
):
2363 if "config" in datacenter_descriptor
:
2364 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2365 #Check that datacenter-type is correct
2366 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2369 module
= "vimconn_" + datacenter_type
2370 module_info
= imp
.find_module(module
)
2371 except (IOError, ImportError):
2372 if module_info
and module_info
[0]:
2373 file.close(module_info
[0])
2374 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2376 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2377 return datacenter_id
2379 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2380 #obtain data, check that only one exist
2381 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2383 datacenter_id
= datacenter
['uuid']
2384 where
={'uuid': datacenter
['uuid']}
2385 if "config" in datacenter_descriptor
:
2386 if datacenter_descriptor
['config']!=None:
2388 new_config_dict
= datacenter_descriptor
["config"]
2391 for k
in new_config_dict
:
2392 if new_config_dict
[k
]==None:
2395 config_dict
= yaml
.load(datacenter
["config"])
2396 config_dict
.update(new_config_dict
)
2400 except Exception as e
:
2401 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2402 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2403 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2404 return datacenter_id
2406 def delete_datacenter(mydb
, datacenter
):
2407 #get nfvo_tenant info
2408 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2409 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2410 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2412 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None):
2413 #get datacenter info
2414 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2415 datacenter_name
=myvim
["name"]
2417 create_vim_tenant
=True if vim_tenant_id
==None and vim_tenant_name
==None else False
2419 #get nfvo_tenant info
2420 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2421 if vim_tenant_name
==None:
2422 vim_tenant_name
=tenant_dict
['name']
2424 #check that this association does not exist before
2425 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2426 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2427 if len(tenants_datacenters
)>0:
2428 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2430 vim_tenant_id_exist_atdb
=False
2431 if not create_vim_tenant
:
2432 where_
={"datacenter_id": datacenter_id
}
2433 if vim_tenant_id
!=None:
2434 where_
["vim_tenant_id"] = vim_tenant_id
2435 if vim_tenant_name
!=None:
2436 where_
["vim_tenant_name"] = vim_tenant_name
2437 #check if vim_tenant_id is already at database
2438 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2439 if len(datacenter_tenants_dict
)>=1:
2440 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2441 vim_tenant_id_exist_atdb
=True
2442 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2444 datacenter_tenants_dict
= {}
2445 #insert at table datacenter_tenants
2446 else: #if vim_tenant_id==None:
2447 #create tenant at VIM if not provided
2449 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2450 except vimconn
.vimconnException
as e
:
2451 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2452 datacenter_tenants_dict
= {}
2453 datacenter_tenants_dict
["created"]="true"
2455 #fill datacenter_tenants table
2456 if not vim_tenant_id_exist_atdb
:
2457 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2458 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2459 datacenter_tenants_dict
["user"] = vim_username
2460 datacenter_tenants_dict
["passwd"] = vim_password
2461 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2462 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2463 datacenter_tenants_dict
["uuid"] = id_
2465 #fill tenants_datacenters table
2466 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2467 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2468 return datacenter_id
2470 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2471 #get datacenter info
2472 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2474 #get nfvo_tenant info
2475 if not tenant_id
or tenant_id
=="any":
2478 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2479 tenant_uuid
= tenant_dict
['uuid']
2481 #check that this association exist before
2482 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2484 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2485 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2486 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2487 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2489 #delete this association
2490 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2492 #get vim_tenant info and deletes
2494 for tenant_datacenter_item
in tenant_datacenter_list
:
2495 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2496 #try to delete vim:tenant
2498 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2499 if vim_tenant_dict
['created']=='true':
2500 #delete tenant at VIM if created by NFVO
2502 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2503 except vimconn
.vimconnException
as e
:
2504 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2505 logger
.warn(warning
)
2506 except db_base_Exception
as e
:
2507 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2508 pass #the error will be caused because dependencies, vim_tenant can not be deleted
2510 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2512 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2514 #get datacenter info
2515 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2517 if 'net-update' in action_dict
:
2519 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2521 except vimconn
.vimconnException
as e
:
2522 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2523 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2524 #update nets Change from VIM format to NFVO format
2527 net_nfvo
={'datacenter_id': datacenter_id
}
2528 net_nfvo
['name'] = net
['name']
2529 #net_nfvo['description']= net['name']
2530 net_nfvo
['vim_net_id'] = net
['id']
2531 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2532 net_nfvo
['shared'] = net
['shared']
2533 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2534 net_list
.append(net_nfvo
)
2535 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2536 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2538 elif 'net-edit' in action_dict
:
2539 net
= action_dict
['net-edit'].pop('net')
2540 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2541 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2542 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2544 elif 'net-delete' in action_dict
:
2545 net
= action_dict
['net-deelte'].get('net')
2546 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2547 result
= mydb
.delete_row(FROM
='datacenter_nets',
2548 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2552 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2554 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2555 #get datacenter info
2556 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2558 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2559 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2560 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2563 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2564 #get datacenter info
2565 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2568 action_dict
= action_dict
["netmap"]
2569 if 'vim_id' in action_dict
:
2570 filter_dict
["id"] = action_dict
['vim_id']
2571 if 'vim_name' in action_dict
:
2572 filter_dict
["name"] = action_dict
['vim_name']
2574 filter_dict
["shared"] = True
2577 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
2578 except vimconn
.vimconnException
as e
:
2579 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
2580 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2581 if len(vim_nets
)>1 and action_dict
:
2582 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
2583 elif len(vim_nets
)==0: # and action_dict:
2584 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
2586 for net
in vim_nets
:
2587 net_nfvo
={'datacenter_id': datacenter_id
}
2588 if action_dict
and "name" in action_dict
:
2589 net_nfvo
['name'] = action_dict
['name']
2591 net_nfvo
['name'] = net
['name']
2592 #net_nfvo['description']= net['name']
2593 net_nfvo
['vim_net_id'] = net
['id']
2594 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2595 net_nfvo
['shared'] = net
['shared']
2596 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2598 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2599 net_nfvo
["status"] = "OK"
2600 net_nfvo
["uuid"] = net_id
2601 except db_base_Exception
as e
:
2605 net_nfvo
["status"] = "FAIL: " + str(e
)
2606 net_list
.append(net_nfvo
)
2609 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2610 #get datacenter info
2611 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2614 if utils
.check_valid_uuid(name
):
2615 filter_dict
["id"] = name
2617 filter_dict
["name"] = name
2619 if item
=="networks":
2620 #filter_dict['tenant_id'] = myvim['tenant_id']
2621 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2622 elif item
=="tenants":
2623 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2625 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2626 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
2627 if name
and len(content
)==1:
2628 return {item
[:-1]: content
[0]}
2629 elif name
and len(content
)==0:
2630 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
2633 return {item
: content
}
2634 except vimconn
.vimconnException
as e
:
2635 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
2636 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
2638 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
2639 #get datacenter info
2640 if tenant_id
== "any":
2643 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2645 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2646 logger
.debug("vim_action_delete vim response: " + str(content
))
2647 items
= content
.values()[0]
2648 if type(items
)==list and len(items
)==0:
2649 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
2650 elif type(items
)==list and len(items
)>1:
2651 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
2652 else: # it is a dict
2653 item_id
= items
["id"]
2654 item_name
= str(items
.get("name"))
2657 if item
=="networks":
2658 content
= myvim
.delete_network(item_id
)
2659 elif item
=="tenants":
2660 content
= myvim
.delete_tenant(item_id
)
2662 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2663 except vimconn
.vimconnException
as e
:
2664 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
2665 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
2667 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
2669 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2670 #get datacenter info
2671 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
2672 if tenant_id
== "any":
2674 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2676 if item
=="networks":
2677 net
= descriptor
["network"]
2678 net_name
= net
.pop("name")
2679 net_type
= net
.pop("type", "bridge")
2680 net_public
= net
.pop("shared", False)
2681 net_ipprofile
= net
.pop("ip_profile", None)
2682 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, **net
)
2683 elif item
=="tenants":
2684 tenant
= descriptor
["tenant"]
2685 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2687 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2688 except vimconn
.vimconnException
as e
:
2689 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
2691 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)