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
39 from db_base
import db_base_Exception
42 global vimconn_imported
45 vimconn_imported
={} #dictionary with VIM type as key, loaded module as value
46 logger
= logging
.getLogger('mano.nfvo')
48 class NfvoException(Exception):
49 def __init__(self
, message
, http_code
):
50 self
.http_code
= http_code
51 Exception.__init
__(self
, message
)
54 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
56 return result, content:
57 <0, error_text upon error
58 nb_records, flavor_list on success
61 WHERE_dict
['vnf_id'] = vnf_id
62 if nfvo_tenant
is not None:
63 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
65 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
66 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
67 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
68 #print "get_flavor_list result:", result
69 #print "get_flavor_list content:", content
71 for flavor
in flavors
:
72 flavorList
.append(flavor
['flavor_id'])
75 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
77 return result, content:
78 <0, error_text upon error
79 nb_records, flavor_list on success
82 WHERE_dict
['vnf_id'] = vnf_id
83 if nfvo_tenant
is not None:
84 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
86 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
87 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
90 imageList
.append(image
['image_id'])
93 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, vim_tenant
=None):
94 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
95 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
96 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
97 raise exception upon error
100 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
101 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
102 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
103 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
104 if nfvo_tenant
or vim_tenant
:
105 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'
106 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
107 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
110 from_
= 'datacenters as d'
111 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
113 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
116 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
117 if vim
["config"] != None:
118 extra
.update(yaml
.load(vim
["config"]))
119 if vim
["type"] not in vimconn_imported
:
122 module
= "vimconn_" + vim
["type"]
123 module_info
= imp
.find_module(module
)
124 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
125 vimconn_imported
[vim
["type"]] = vim_conn
126 except (IOError, ImportError) as e
:
127 if module_info
and module_info
[0]:
128 file.close(module_info
[0])
129 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
130 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
134 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
135 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
136 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
137 tenant_id
=vim
.get('vim_tenant_id'), tenant_name
=vim
.get('vim_tenant_name'),
138 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
139 user
=vim
.get('user'), passwd
=vim
.get('passwd'),
142 except Exception as e
:
143 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
145 except db_base_Exception
as e
:
146 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
148 def rollback(mydb
, vims
, rollback_list
):
150 #delete things by reverse order
151 for i
in range(len(rollback_list
)-1, -1, -1):
152 item
= rollback_list
[i
]
153 if item
["where"]=="vim":
154 if item
["vim_id"] not in vims
:
156 vim
=vims
[ item
["vim_id"] ]
158 if item
["what"]=="image":
159 vim
.delete_image(item
["uuid"])
160 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
161 elif item
["what"]=="flavor":
162 vim
.delete_flavor(item
["uuid"])
163 mydb
.delete_row(FROM
="datacenters_flavos", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
164 elif item
["what"]=="network":
165 vim
.delete_network(item
["uuid"])
166 elif item
["what"]=="vm":
167 vim
.delete_vminstance(item
["uuid"])
168 except vimconn
.vimconnException
as e
:
169 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
170 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
171 except db_base_Exception
as e
:
172 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
176 if item
["what"]=="image":
177 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
178 elif item
["what"]=="flavor":
179 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
180 except db_base_Exception
as e
:
181 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
182 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
183 if len(undeleted_items
)==0:
184 return True," Rollback successful."
186 return False," Rollback fails to delete: " + str(undeleted_items
)
188 def check_vnf_descriptor(vnf_descriptor
):
190 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
192 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
194 #dataplane interfaces
195 for numa
in vnfc
.get("numas",() ):
196 for interface
in numa
.get("interfaces",()):
197 if interface
["name"] in name_list
:
198 raise NfvoException("Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC"\
199 .format(vnfc
["name"], interface
["name"]),
201 name_list
.append( interface
["name"] )
203 for interface
in vnfc
.get("bridge-ifaces",() ):
204 if interface
["name"] in name_list
:
205 raise NfvoException("Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC"\
206 .format(vnfc
["name"], interface
["name"]),
208 name_list
.append( interface
["name"] )
209 vnfc_interfaces
[ vnfc
["name"] ] = name_list
211 #check if the info in external_connections matches with the one in the vnfcs
213 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
214 if external_connection
["name"] in name_list
:
215 raise NfvoException("Error at vnf:external-connections:name, value '{}' already used as an external-connection"\
216 .format(external_connection
["name"]),
218 name_list
.append(external_connection
["name"])
219 if external_connection
["VNFC"] not in vnfc_interfaces
:
220 raise NfvoException("Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC"\
221 .format(external_connection
["name"], external_connection
["VNFC"]),
224 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
225 raise NfvoException("Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC"\
226 .format(external_connection
["name"], external_connection
["local_iface_name"]),
229 #check if the info in internal_connections matches with the one in the vnfcs
231 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
232 if internal_connection
["name"] in name_list
:
233 raise NfvoException("Error at vnf:internal-connections:name, value '%s' already used as an internal-connection"\
234 .format(internal_connection
["name"]),
236 name_list
.append(internal_connection
["name"])
237 #We should check that internal-connections of type "ptp" have only 2 elements
238 if len(internal_connection
["elements"])>2 and internal_connection
["type"] == "ptp":
239 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements, size must be 2 for a type:'ptp'"\
240 .format(internal_connection
["name"]),
242 for port
in internal_connection
["elements"]:
243 if port
["VNFC"] not in vnfc_interfaces
:
244 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC"\
245 .format(internal_connection
["name"], port
["VNFC"]),
247 if port
["local_iface_name"] not in vnfc_interfaces
[ port
["VNFC"] ]:
248 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC"\
249 .format(internal_connection
["name"], port
["local_iface_name"]),
251 return -HTTP_Bad_Request
,
253 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
255 if only_create_at_vim
:
256 image_mano_id
= image_dict
['uuid']
258 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
260 image_mano_id
= images
[0]['uuid']
263 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
264 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None)
266 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
267 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
268 #create image at every vim
269 for vim_id
,vim
in vims
.iteritems():
270 image_created
="false"
272 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
273 #look at VIM if this image exist
275 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
276 except vimconn
.vimconnNotFoundException
as e
:
277 #Create the image in VIM
279 image_vim_id
= vim
.new_image(image_dict
)
280 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
282 except vimconn
.vimconnException
as e
:
284 logger
.error("Error creating image at VIM: %s", str(e
))
286 image_vim_id
= str(e
)
287 logger
.warn("Error creating image at VIM: %s", str(e
))
289 except vimconn
.vimconnException
as e
:
290 logger
.warn("Error contacting VIM to know if the image exist at VIM: %s", str(e
))
291 image_vim_id
= str(e
)
293 #if reach here the image has been create or exist
295 #add new vim_id at datacenters_images
296 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
297 elif image_db
[0]["vim_id"]!=image_vim_id
:
298 #modify existing vim_id at datacenters_images
299 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
301 return image_vim_id
if only_create_at_vim
else image_mano_id
303 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
304 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
305 'ram':flavor_dict
.get('ram'),
306 'vcpus':flavor_dict
.get('vcpus'),
308 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
309 del flavor_dict
['extended']
310 if 'extended' in flavor_dict
:
311 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
313 #look if flavor exist
314 if only_create_at_vim
:
315 flavor_mano_id
= flavor_dict
['uuid']
317 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
319 flavor_mano_id
= flavors
[0]['uuid']
322 #create one by one the images of aditional disks
323 dev_image_list
=[] #list of images
324 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
326 for device
in flavor_dict
['extended'].get('devices',[]):
327 if "image" not in device
:
329 image_dict
={'location':device
['image'], 'name':flavor_dict
['name']+str(dev_nb
)+"-img", 'description':flavor_dict
.get('description')}
330 image_metadata_dict
= device
.get('image metadata', None)
331 image_metadata_str
= None
332 if image_metadata_dict
!= None:
333 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
334 image_dict
['metadata']=image_metadata_str
335 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
336 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
337 dev_image_list
.append(image_id
)
339 temp_flavor_dict
['name'] = flavor_dict
['name']
340 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
341 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
342 flavor_mano_id
= content
343 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
344 #create flavor at every vim
345 if 'uuid' in flavor_dict
:
346 del flavor_dict
['uuid']
348 for vim_id
,vim
in vims
.items():
349 flavor_created
="false"
351 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
352 #look at VIM if this flavor exist SKIPPED
353 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
355 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
359 #Create the flavor in VIM
360 #Translate images at devices from MANO id to VIM id
361 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
362 #make a copy of original devices
364 for device
in flavor_dict
["extended"].get("devices",[]):
367 devices_original
.append(dev
)
368 if 'image' in device
:
370 if 'image metadata' in device
:
371 del device
['image metadata']
373 for index
in range(0,len(devices_original
)) :
374 device
=devices_original
[index
]
375 if "image" not in device
:
377 image_dict
={'location':device
['image'], 'name':flavor_dict
['name']+str(dev_nb
)+"-img", 'description':flavor_dict
.get('description')}
378 image_metadata_dict
= device
.get('image metadata', None)
379 image_metadata_str
= None
380 if image_metadata_dict
!= None:
381 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
382 image_dict
['metadata']=image_metadata_str
383 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
384 image_dict
["uuid"]=image_mano_id
385 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
386 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
389 #check that this vim_id exist in VIM, if not create
390 flavor_vim_id
=flavor_db
[0]["vim_id"]
392 vim
.get_flavor(flavor_vim_id
)
393 continue #flavor exist
394 except vimconn
.vimconnException
:
396 #create flavor at vim
397 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
399 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
400 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
401 flavor_created
="true"
402 except vimconn
.vimconnException
as e
:
404 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
406 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
408 #if reach here the flavor has been create or exist
409 if len(flavor_db
)==0:
410 #add new vim_id at datacenters_flavors
411 mydb
.new_row('datacenters_flavors', {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
, 'created':flavor_created
})
412 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
413 #modify existing vim_id at datacenters_flavors
414 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
416 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
418 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
421 # Step 1. Check the VNF descriptor
422 check_vnf_descriptor(vnf_descriptor
)
423 # Step 2. Check tenant exist
424 if tenant_id
!= "any":
425 check_tenant(mydb
, tenant_id
)
426 if "tenant_id" in vnf_descriptor
["vnf"]:
427 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
428 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
431 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
432 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
433 vims
= get_vim(mydb
, tenant_id
)
437 # Step 4. Review the descriptor and add missing fields
438 #print vnf_descriptor
439 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
440 vnf_name
= vnf_descriptor
['vnf']['name']
441 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
442 if "physical" in vnf_descriptor
['vnf']:
443 del vnf_descriptor
['vnf']['physical']
444 #print vnf_descriptor
445 # Step 5. Check internal connections
446 # TODO: to be moved to step 1????
447 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
448 for ic
in internal_connections
:
449 if len(ic
['elements'])>2 and ic
['type']=='ptp':
450 raise NfvoException("Mismatch 'type':'ptp' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'data'".format(len(ic
), ic
['name']),
452 elif len(ic
['elements'])==2 and ic
['type']=='data':
453 raise NfvoException("Mismatch 'type':'data' with 2 elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'ptp'".format(ic
['name']),
456 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
457 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
458 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
460 #For each VNFC, we add it to the VNFCDict and we create a flavor.
461 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
462 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
464 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
465 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
467 VNFCitem
["name"] = vnfc
['name']
468 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
470 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
473 myflavorDict
["name"] = vnfc
['name']+"-flv"
474 myflavorDict
["description"] = VNFCitem
["description"]
475 myflavorDict
["ram"] = vnfc
.get("ram", 0)
476 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
477 myflavorDict
["disk"] = vnfc
.get("disk", 1)
478 myflavorDict
["extended"] = {}
480 devices
= vnfc
.get("devices")
482 myflavorDict
["extended"]["devices"] = devices
485 # 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
486 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
488 # Previous code has been commented
489 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
490 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
491 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
492 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
494 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
496 # print "Error creating flavor: unknown processor model. Rollback successful."
497 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
499 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
500 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
502 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
503 myflavorDict
['extended']['numas'] = vnfc
['numas']
507 # Step 6.2 New flavors are created in the VIM
508 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
510 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
511 VNFCitem
["flavor_id"] = flavor_id
512 VNFCDict
[vnfc
['name']] = VNFCitem
514 logger
.debug("Creating new images in the VIM for each VNFC")
515 # Step 6.3 New images are created in the VIM
516 #For each VNFC, we must create the appropriate image.
517 #This "for" loop might be integrated with the previous one
518 #In case this integration is made, the VNFCDict might become a VNFClist.
519 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
520 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
521 image_dict
={'location':vnfc
['VNFC image'], 'name':vnfc
['name']+"-img", 'description':VNFCDict
[vnfc
['name']]['description']}
522 image_metadata_dict
= vnfc
.get('image metadata', None)
523 image_metadata_str
= None
524 if image_metadata_dict
is not None:
525 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
526 image_dict
['metadata']=image_metadata_str
527 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
528 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
529 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
530 VNFCDict
[vnfc
['name']]["image_id"] = image_id
531 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
['VNFC image']
534 # Step 7. Storing the VNF descriptor in the repository
535 if "descriptor" not in vnf_descriptor
["vnf"]:
536 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
538 # Step 8. Adding the VNF to the NFVO DB
539 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
541 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
542 _
, message
= rollback(mydb
, vims
, rollback_list
)
543 if isinstance(e
, db_base_Exception
):
544 error_text
= "Exception at database"
545 elif isinstance(e
, KeyError):
546 error_text
= "KeyError exception "
547 e
.http_code
= HTTP_Internal_Server_Error
549 error_text
= "Exception at VIM"
550 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
551 #logger.error("start_scenario %s", error_text)
552 raise NfvoException(error_text
, e
.http_code
)
554 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
555 #check valid tenant_id
556 check_tenant(mydb
, tenant_id
)
559 if tenant_id
!= "any":
560 where_or
["tenant_id"] = tenant_id
561 where_or
["public"] = True
562 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
565 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
566 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
567 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
568 data
={'vnf' : filtered_content
}
570 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
571 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description'),
572 WHERE
={'vnfs.uuid': vnf_id
} )
574 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
576 data
['vnf']['VNFC'] = content
578 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
579 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
580 WHERE
={'vnfs.uuid': vnf_id
} )
581 data
['vnf']['nets'] = content
583 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
584 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
585 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
586 WHERE
={'vnfs.uuid': vnf_id
},
587 WHERE_NOT
={'interfaces.external_name': None} )
589 data
['vnf']['external-connections'] = content
593 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
595 if tenant_id
!= "any":
596 check_tenant(mydb
, tenant_id
)
597 # Get the URL of the VIM from the nfvo_tenant and the datacenter
598 vims
= get_vim(mydb
, tenant_id
)
602 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
604 if tenant_id
!= "any":
605 where_or
["tenant_id"] = tenant_id
606 where_or
["public"] = True
607 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
610 # "Getting the list of flavors and tenants of the VNF"
611 flavorList
= get_flavorlist(mydb
, vnf_id
)
612 if len(flavorList
)==0:
613 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
615 imageList
= get_imagelist(mydb
, vnf_id
)
616 if len(imageList
)==0:
617 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
619 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
621 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
624 for flavor
in flavorList
:
625 #check if flavor is used by other vnf
627 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
629 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
631 #flavor not used, must be deleted
633 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
635 if flavor_vim
["datacenter_id"] not in vims
:
637 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
639 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
641 myvim
.delete_flavor(flavor_vim
["vim_id"])
642 except vimconn
.vimconnNotFoundException
as e
:
643 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
644 except vimconn
.vimconnException
as e
:
645 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
646 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
647 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
648 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
649 mydb
.delete_row_by_id('flavors', flavor
)
650 except db_base_Exception
as e
:
651 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
652 undeletedItems
.append("flavor %s" % flavor
)
655 for image
in imageList
:
657 #check if image is used by other vnf
658 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
660 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
662 #image not used, must be deleted
664 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
666 if image_vim
["datacenter_id"] not in vims
:
668 if image_vim
['created']=='false': #skip this image because not created by openmano
670 myvim
=vims
[ image_vim
["datacenter_id"] ]
672 myvim
.delete_image(image_vim
["vim_id"])
673 except vimconn
.vimconnNotFoundException
as e
:
674 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
675 except vimconn
.vimconnException
as e
:
676 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
677 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
678 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
679 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
680 mydb
.delete_row_by_id('images', image
)
681 except db_base_Exception
as e
:
682 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
683 undeletedItems
.append("image %s" % image
)
685 return vnf_id
+ " " + vnf
["name"]
687 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
689 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
690 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
694 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
695 myvim
= vims
.values()[0]
696 result
,servers
= myvim
.get_hosts_info()
698 return result
, servers
699 topology
= {'name':myvim
['name'] , 'servers': servers
}
700 return result
, topology
702 def get_hosts(mydb
, nfvo_tenant_id
):
703 vims
= get_vim(mydb
, nfvo_tenant_id
)
705 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
707 #print "nfvo.datacenter_action() error. Several datacenters found"
708 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
709 myvim
= vims
.values()[0]
711 hosts
= myvim
.get_hosts()
712 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
714 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
716 server
={'name':host
['name'], 'vms':[]}
717 for vm
in host
['instances']:
718 #get internal name and model
720 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
721 WHERE
={'vim_vm_id':vm
['id']} )
723 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
725 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
727 except db_base_Exception
as e
:
728 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
729 datacenter
['Datacenters'][0]['servers'].append(server
)
730 #return -400, "en construccion"
732 #print 'datacenters '+ json.dumps(datacenter, indent=4)
734 except vimconn
.vimconnException
as e
:
735 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
737 def new_scenario(mydb
, tenant_id
, topo
):
739 # result, vims = get_vim(mydb, tenant_id)
741 # return result, vims
743 if tenant_id
!= "any":
744 check_tenant(mydb
, tenant_id
)
745 if "tenant_id" in topo
:
746 if topo
["tenant_id"] != tenant_id
:
747 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
752 #1.1: get VNFs and external_networks (other_nets).
754 other_nets
={} #external_networks, bridge_networks and data_networkds
755 nodes
= topo
['topology']['nodes']
756 for k
in nodes
.keys():
757 if nodes
[k
]['type'] == 'VNF':
759 vnfs
[k
]['ifaces'] = {}
760 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
761 other_nets
[k
] = nodes
[k
]
762 other_nets
[k
]['external']=True
763 elif nodes
[k
]['type'] == 'network':
764 other_nets
[k
] = nodes
[k
]
765 other_nets
[k
]['external']=False
768 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
769 for name
,vnf
in vnfs
.items():
771 where_or
={"tenant_id": tenant_id
, 'public': "true"}
773 error_pos
= "'topology':'nodes':'" + name
+ "'"
775 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
776 where
['uuid'] = vnf
['vnf_id']
777 if 'VNF model' in vnf
:
778 error_text
+= " 'VNF model' " + vnf
['VNF model']
779 where
['name'] = vnf
['VNF model']
781 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
783 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
789 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
791 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
792 vnf
['uuid']=vnf_db
[0]['uuid']
793 vnf
['description']=vnf_db
[0]['description']
794 #get external interfaces
795 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
796 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
797 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
798 for ext_iface
in ext_ifaces
:
799 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
801 #1.4 get list of connections
802 conections
= topo
['topology']['connections']
804 for k
in conections
.keys():
805 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
806 ifaces_list
= conections
[k
]['nodes'].items()
807 elif type(conections
[k
]['nodes'])==list: #list with dictionary
809 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
810 for k2
in conection_pair_list
:
813 con_type
= conections
[k
].get("type", "link")
814 if con_type
!= "link":
816 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
817 other_nets
[k
] = {'external': False}
818 if conections
[k
].get("graph"):
819 other_nets
[k
]["graph"] = conections
[k
]["graph"]
820 ifaces_list
.append( (k
, None) )
823 if con_type
== "external_network":
824 other_nets
[k
]['external'] = True
825 if conections
[k
].get("model"):
826 other_nets
[k
]["model"] = conections
[k
]["model"]
828 other_nets
[k
]["model"] = k
829 if con_type
== "dataplane_net" or con_type
== "bridge_net":
830 other_nets
[k
]["model"] = con_type
833 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)
834 #print set(ifaces_list)
835 #check valid VNF and iface names
836 for iface
in ifaces_list
:
837 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
838 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
839 str(k
), iface
[0]), HTTP_Not_Found
)
840 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
841 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
842 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
844 #1.5 unify connections from the pair list to a consolidated list
846 while index
< len(conections_list
):
848 while index2
< len(conections_list
):
849 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
850 conections_list
[index
] |
= conections_list
[index2
]
851 del conections_list
[index2
]
854 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
856 #for k in conections_list:
861 #1.6 Delete non external nets
862 # for k in other_nets.keys():
863 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
864 # for con in conections_list:
866 # for index in range(0,len(con)):
867 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
868 # for index in delete_indexes:
871 #1.7: Check external_ports are present at database table datacenter_nets
872 for k
,net
in other_nets
.items():
873 error_pos
= "'topology':'nodes':'" + k
+ "'"
874 if net
['external']==False:
875 if 'name' not in net
:
877 if 'model' not in net
:
878 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
879 if net
['model']=='bridge_net':
880 net
['type']='bridge';
881 elif net
['model']=='dataplane_net':
884 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
886 #IF we do not want to check that external network exist at datacenter
891 # if 'net_id' in net:
892 # error_text += " 'net_id' " + net['net_id']
893 # WHERE_['uuid'] = net['net_id']
895 # error_text += " 'model' " + net['model']
896 # WHERE_['name'] = net['model']
897 # if len(WHERE_) == 0:
898 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
899 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
900 # FROM='datacenter_nets', WHERE=WHERE_ )
902 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
904 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
905 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
907 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
908 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
909 # other_nets[k].update(net_db[0])
912 net_nb
=0 #Number of nets
913 for con
in conections_list
:
914 #check if this is connected to a external net
918 for index
in range(0,len(con
)):
919 #check if this is connected to a external net
920 for net_key
in other_nets
.keys():
921 if con
[index
][0]==net_key
:
922 if other_net_index
>=0:
923 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
924 #print "nfvo.new_scenario " + error_text
925 raise NfvoException(error_text
, HTTP_Bad_Request
)
927 other_net_index
= index
930 #print "other_net_index", other_net_index
932 if other_net_index
>=0:
933 del con
[other_net_index
]
934 #IF we do not want to check that external network exist at datacenter
935 if other_nets
[net_target
]['external'] :
936 if "name" not in other_nets
[net_target
]:
937 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
938 if other_nets
[net_target
]["type"] == "external_network":
939 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
940 other_nets
[net_target
]["type"] = "data"
942 other_nets
[net_target
]["type"] = "bridge"
944 # if other_nets[net_target]['external'] :
945 # 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
946 # if type_=='data' and other_nets[net_target]['type']=="ptp":
947 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
948 # print "nfvo.new_scenario " + error_text
949 # return -HTTP_Bad_Request, error_text
952 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
955 net_type_bridge
=False
957 net_target
= "__-__net"+str(net_nb
)
958 net_list
[net_target
] = {'name': "net-"+str(net_nb
), 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
961 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
962 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
963 if iface_type
=='mgmt' or iface_type
=='bridge':
964 net_type_bridge
= True
967 if net_type_bridge
and net_type_data
:
968 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
969 #print "nfvo.new_scenario " + error_text
970 raise NfvoException(error_text
, HTTP_Bad_Request
)
971 elif net_type_bridge
:
974 type_
='data' if len(con
)>2 else 'ptp'
975 net_list
[net_target
]['type'] = type_
978 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
979 #print "nfvo.new_scenario " + error_text
981 raise NfvoException(error_text
, HTTP_Bad_Request
)
983 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
984 #1.8.1 obtain management net
985 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
986 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
987 #1.8.2 check all interfaces from all vnfs
990 for vnf
in vnfs
.values():
991 for iface
in vnf
['ifaces'].values():
992 if iface
['type']=='mgmt' and 'net_key' not in iface
:
994 iface
['net_key'] = 'mgmt'
996 if add_mgmt_net
and 'mgmt' not in net_list
:
997 net_list
['mgmt']=mgmt_net
[0]
998 net_list
['mgmt']['external']=True
999 net_list
['mgmt']['graph']={'visible':False}
1001 net_list
.update(other_nets
)
1003 #print 'net_list', net_list
1008 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1009 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1010 'tenant_id':tenant_id
, 'name':topo
['name'],
1011 'description':topo
.get('description',topo
['name']),
1012 'public': topo
.get('public', False)
1017 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
):
1018 scenario
= scenario_dict
["scenario"]
1019 if tenant_id
!= "any":
1020 check_tenant(mydb
, tenant_id
)
1021 if "tenant_id" in scenario
:
1022 if scenario
["tenant_id"] != tenant_id
:
1023 print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1024 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1025 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1029 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1030 for name
,vnf
in scenario
["vnfs"].iteritems():
1032 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1034 error_pos
= "'topology':'nodes':'" + name
+ "'"
1036 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1037 where
['uuid'] = vnf
['vnf_id']
1038 if 'vnf_name' in vnf
:
1039 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1040 where
['name'] = vnf
['vnf_name']
1042 raise NfvoException("Needed a 'vnf_id' or 'VNF model' at " + error_pos
, HTTP_Bad_Request
)
1043 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1049 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1051 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1052 vnf
['uuid']=vnf_db
[0]['uuid']
1053 vnf
['description']=vnf_db
[0]['description']
1055 #get external interfaces
1056 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1057 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1058 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1059 for ext_iface
in ext_ifaces
:
1060 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1062 #2: Insert net_key at every vnf interface
1063 for net_name
,net
in scenario
["networks"].iteritems():
1064 net_type_bridge
=False
1066 for iface_dict
in net
["interfaces"]:
1067 for vnf
,iface
in iface_dict
.iteritems():
1068 if vnf
not in scenario
["vnfs"]:
1069 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1070 #print "nfvo.new_scenario_v02 " + error_text
1071 raise NfvoException(error_text
, HTTP_Not_Found
)
1072 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1073 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1074 #print "nfvo.new_scenario_v02 " + error_text
1075 raise NfvoException(error_text
, HTTP_Bad_Request
)
1076 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1077 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1078 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1079 #print "nfvo.new_scenario_v02 " + error_text
1080 raise NfvoException(error_text
, HTTP_Bad_Request
)
1081 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1082 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1083 if iface_type
=='mgmt' or iface_type
=='bridge':
1084 net_type_bridge
= True
1086 net_type_data
= True
1087 if net_type_bridge
and net_type_data
:
1088 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1089 #print "nfvo.new_scenario " + error_text
1090 raise NfvoException(error_text
, HTTP_Bad_Request
)
1091 elif net_type_bridge
:
1094 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1096 net
['name'] = net_name
1097 net
['external'] = net
.get('external', False)
1099 #3: insert at database
1100 scenario
["nets"] = scenario
["networks"]
1101 scenario
['tenant_id'] = tenant_id
1102 scenario_id
= mydb
.new_scenario( scenario
)
1105 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1106 data
["uuid"] = scenario_id
1107 data
["tenant_id"] = tenant_id
1108 c
= mydb
.edit_scenario( data
)
1111 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1112 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1113 datacenter_id
= None
1114 datacenter_name
=None
1115 if datacenter
!= None:
1116 if utils
.check_valid_uuid(datacenter
):
1117 datacenter_id
= datacenter
1119 datacenter_name
= datacenter
1120 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
)
1122 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
1124 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
1125 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1126 myvim
= vims
.values()[0]
1127 myvim_tenant
= myvim
['tenant_id']
1128 datacenter_id
= myvim
['id']
1129 datacenter_name
= myvim
['name']
1130 datacenter_tenant_id
= myvim
['config']['datacenter_tenant_id']
1133 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1134 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1135 scenarioDict
['datacenter_tenant_id'] = datacenter_tenant_id
1136 scenarioDict
['datacenter_id'] = datacenter_id
1137 #print '================scenarioDict======================='
1138 #print json.dumps(scenarioDict, indent=4)
1139 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1141 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1142 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1144 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1145 auxNetDict
['scenario'] = {}
1147 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1148 for sce_net
in scenarioDict
['nets']:
1149 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1151 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1152 myNetName
= myNetName
[0:255] #limit length
1153 myNetType
= sce_net
['type']
1155 myNetDict
["name"] = myNetName
1156 myNetDict
["type"] = myNetType
1157 myNetDict
["tenant_id"] = myvim_tenant
1159 #We should use the dictionary as input parameter for new_network
1161 if not sce_net
["external"]:
1162 network_id
= myvim
.new_network(myNetName
, myNetType
)
1163 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1164 sce_net
['vim_id'] = network_id
1165 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1166 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1168 if sce_net
['vim_id'] == None:
1169 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1170 _
, message
= rollback(mydb
, vims
, rollbackList
)
1171 logger
.error("nfvo.start_scenario: %s", error_text
)
1172 raise NfvoException(error_text
, HTTP_Bad_Request
)
1173 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1174 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1176 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1177 #For each vnf net, we create it and we add it to instanceNetlist.
1178 for sce_vnf
in scenarioDict
['vnfs']:
1179 for net
in sce_vnf
['nets']:
1180 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1182 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1183 myNetName
= myNetName
[0:255] #limit length
1184 myNetType
= net
['type']
1186 myNetDict
["name"] = myNetName
1187 myNetDict
["type"] = myNetType
1188 myNetDict
["tenant_id"] = myvim_tenant
1191 #We should use the dictionary as input parameter for new_network
1192 network_id
= myvim
.new_network(myNetName
, myNetType
)
1193 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1194 net
['vim_id'] = network_id
1195 if sce_vnf
['uuid'] not in auxNetDict
:
1196 auxNetDict
[sce_vnf
['uuid']] = {}
1197 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1198 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1200 #print "auxNetDict:"
1201 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1203 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1204 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1206 for sce_vnf
in scenarioDict
['vnfs']:
1207 for vm
in sce_vnf
['vms']:
1210 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1211 myVMDict
['name'] = "%s.%s.%d" % (instance_scenario_name
,sce_vnf
['name'],i
)
1212 #myVMDict['description'] = vm['description']
1213 myVMDict
['description'] = myVMDict
['name'][0:99]
1215 myVMDict
['start'] = "no"
1216 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1217 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1219 #create image at vim in case it not exist
1220 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1221 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1222 vm
['vim_image_id'] = image_id
1224 #create flavor at vim in case it not exist
1225 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1226 if flavor_dict
['extended']!=None:
1227 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1228 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1229 vm
['vim_flavor_id'] = flavor_id
1232 myVMDict
['imageRef'] = vm
['vim_image_id']
1233 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1234 myVMDict
['networks'] = []
1235 for iface
in vm
['interfaces']:
1237 if iface
['type']=="data":
1238 netDict
['type'] = iface
['model']
1239 elif "model" in iface
and iface
["model"]!=None:
1240 netDict
['model']=iface
['model']
1241 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1242 #discover type of interface looking at flavor
1243 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1244 for flavor_iface
in numa
.get('interfaces',[]):
1245 if flavor_iface
.get('name') == iface
['internal_name']:
1246 if flavor_iface
['dedicated'] == 'yes':
1247 netDict
['type']="PF" #passthrough
1248 elif flavor_iface
['dedicated'] == 'no':
1249 netDict
['type']="VF" #siov
1250 elif flavor_iface
['dedicated'] == 'yes:sriov':
1251 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1252 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1254 netDict
["use"]=iface
['type']
1255 if netDict
["use"]=="data" and not netDict
.get("type"):
1256 #print "netDict", netDict
1257 #print "iface", iface
1258 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'])
1259 if flavor_dict
.get('extended')==None:
1260 raise NfvoException(e_text
+ "After database migration some information is not available. \
1261 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1263 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1264 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1265 netDict
["type"]="virtual"
1266 if "vpci" in iface
and iface
["vpci"] is not None:
1267 netDict
['vpci'] = iface
['vpci']
1268 if "mac" in iface
and iface
["mac"] is not None:
1269 netDict
['mac_address'] = iface
['mac']
1270 netDict
['name'] = iface
['internal_name']
1271 if iface
['net_id'] is None:
1272 for vnf_iface
in sce_vnf
["interfaces"]:
1275 if vnf_iface
['interface_id']==iface
['uuid']:
1276 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1279 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1280 #skip bridge ifaces not connected to any net
1281 #if 'net_id' not in netDict or netDict['net_id']==None:
1283 myVMDict
['networks'].append(netDict
)
1284 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1285 #print myVMDict['name']
1286 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1287 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1288 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1289 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1290 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1291 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1292 vm
['vim_id'] = vm_id
1293 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1294 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1295 for net
in myVMDict
['networks']:
1297 for iface
in vm
['interfaces']:
1298 if net
["name"]==iface
["internal_name"]:
1299 iface
["vim_id"]=net
["vim_id"]
1302 logger
.debug("start scenario Deployment done")
1303 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1304 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1305 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1306 return mydb
.get_instance_scenario(instance_id
)
1308 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1309 _
, message
= rollback(mydb
, vims
, rollbackList
)
1310 if isinstance(e
, db_base_Exception
):
1311 error_text
= "Exception at database"
1313 error_text
= "Exception at VIM"
1314 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1315 #logger.error("start_scenario %s", error_text)
1316 raise NfvoException(error_text
, e
.http_code
)
1319 def unify_cloud_config(cloud_config
):
1320 index_to_delete
= []
1321 users
= cloud_config
.get("users", [])
1322 for index0
in range(0,len(users
)):
1323 if index0
in index_to_delete
:
1325 for index1
in range(index0
+1,len(users
)):
1326 if index1
in index_to_delete
:
1328 if users
[index0
]["name"] == users
[index1
]["name"]:
1329 index_to_delete
.append(index1
)
1330 for key
in users
[index1
].get("key-pairs",()):
1331 if "key-pairs" not in users
[index0
]:
1332 users
[index0
]["key-pairs"] = [key
]
1333 elif key
not in users
[index0
]["key-pairs"]:
1334 users
[index0
]["key-pairs"].append(key
)
1335 index_to_delete
.sort(reverse
=True)
1336 for index
in index_to_delete
:
1339 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None):
1340 datacenter_id
= None
1341 datacenter_name
= None
1342 if datacenter_id_name
:
1343 if utils
.check_valid_uuid(datacenter_id_name
):
1344 datacenter_id
= datacenter_id_name
1346 datacenter_name
= datacenter_id_name
1347 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
=None)
1349 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1351 #print "nfvo.datacenter_action() error. Several datacenters found"
1352 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1353 return vims
.keys()[0], vims
.values()[0]
1355 def create_instance(mydb
, tenant_id
, instance_dict
):
1356 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1357 logger
.debug("Creating instance...")
1358 scenario
= instance_dict
["scenario"]
1360 #find main datacenter
1362 datacenter
= instance_dict
.get("datacenter")
1363 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1364 myvims
[default_datacenter_id
] = vim
1365 #myvim_tenant = myvim['tenant_id']
1366 # default_datacenter_name = vim['name']
1367 default_datacenter_tenant_id
= vim
['config']['datacenter_tenant_id'] #TODO revisar
1370 #print "Checking that the scenario exists and getting the scenario dictionary"
1371 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1372 scenarioDict
['datacenter_tenant_id'] = default_datacenter_tenant_id
1373 scenarioDict
['datacenter_id'] = default_datacenter_id
1375 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1376 auxNetDict
['scenario'] = {}
1378 print "scenario dict: ",yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False) #TODO quitar
1379 instance_name
= instance_dict
["name"]
1380 instance_description
= instance_dict
.get("description")
1382 #0 check correct parameters
1383 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1385 for scenario_net
in scenarioDict
['nets']:
1386 if net_name
== scenario_net
["name"]:
1390 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1391 if "sites" not in net_instance_desc
:
1392 net_instance_desc
["sites"] = [ {} ]
1393 site_without_datacenter_field
= False
1394 for site
in net_instance_desc
["sites"]:
1395 if site
.get("datacenter"):
1396 if site
["datacenter"] not in myvims
:
1397 #Add this datacenter to myvims
1398 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1400 site
["datacenter"] = d
#change name to id
1402 if site_without_datacenter_field
:
1403 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1404 site_without_datacenter_field
= True
1405 site
["datacenter"] = default_datacenter_id
#change name to id
1407 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
1409 for scenario_vnf
in scenarioDict
['vnfs']:
1410 if vnf_name
== scenario_vnf
['name']:
1414 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
1415 if "datacenter" in vnf_instance_desc
:
1416 #Add this datacenter to myvims
1417 if vnf_instance_desc
["datacenter"] not in myvims
:
1418 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
1420 scenario_vnf
["datacenter"] = d
#change name to id
1421 #0.1 parse cloud-config parameters
1422 cloud_config
= scenarioDict
.get("cloud-config", {})
1423 if instance_dict
.get("cloud-config"):
1424 cloud_config
.update( instance_dict
["cloud-config"])
1425 if not cloud_config
:
1428 scenarioDict
["cloud-config"] = cloud_config
1429 unify_cloud_config(cloud_config
)
1431 #1. Creating new nets (sce_nets) in the VIM"
1432 for sce_net
in scenarioDict
['nets']:
1433 sce_net
["vim_id_sites"]={}
1434 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
1435 net_name
= descriptor_net
.get("vim-network-name")
1436 auxNetDict
['scenario'][sce_net
['uuid']] = {}
1438 sites
= descriptor_net
.get("sites", [ {} ])
1440 if site
.get("datacenter"):
1441 vim
= myvims
[ site
["datacenter"] ]
1442 datacenter_id
= site
["datacenter"]
1444 vim
= myvims
[ default_datacenter_id
]
1445 datacenter_id
= default_datacenter_id
1447 net_type
= sce_net
['type']
1448 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
1449 if sce_net
["external"]:
1451 net_name
= sce_net
["name"]
1452 if "netmap-use" in site
or "netmap-create" in site
:
1453 create_network
= False
1454 lookfor_network
= False
1455 if "netmap-use" in site
:
1456 lookfor_network
= True
1457 if utils
.check_valid_uuid(site
["netmap-use"]):
1458 filter_text
= "scenario id '%s'" % site
["netmap-use"]
1459 lookfor_filter
["id"] = site
["netmap-use"]
1461 filter_text
= "scenario name '%s'" % site
["netmap-use"]
1462 lookfor_filter
["name"] = site
["netmap-use"]
1463 if "netmap-create" in site
:
1464 create_network
= True
1465 net_vim_name
= net_name
1466 if site
["netmap-create"]:
1467 net_vim_name
= site
["netmap-create"]
1469 elif sce_net
['vim_id'] != None:
1470 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
1471 create_network
= False
1472 lookfor_network
= True
1473 lookfor_filter
["id"] = sce_net
['vim_id']
1474 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
1475 #look for network at datacenter and return error
1477 #There is not a netmap, look at datacenter for a net with this name and create if not found
1478 create_network
= True
1479 lookfor_network
= True
1480 lookfor_filter
["name"] = sce_net
["name"]
1481 net_vim_name
= sce_net
["name"]
1482 filter_text
= "scenario name '%s'" % sce_net
["name"]
1485 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
1486 net_name
= net_name
[:255] #limit length
1487 net_vim_name
= net_name
1488 create_network
= True
1489 lookfor_network
= False
1492 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
1493 if len(vim_nets
) > 1:
1494 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1495 elif len(vim_nets
) == 0:
1496 if not create_network
:
1497 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1499 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
1501 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
1502 create_network
= False
1504 #if network is not external
1505 network_id
= vim
.new_network(net_vim_name
, net_type
)
1506 sce_net
["vim_id_sites"][datacenter_id
] = network_id
1507 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = network_id
1508 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':network_id
})
1510 #2. Creating new nets (vnf internal nets) in the VIM"
1511 #For each vnf net, we create it and we add it to instanceNetlist.
1512 for sce_vnf
in scenarioDict
['vnfs']:
1513 for net
in sce_vnf
['nets']:
1514 if sce_vnf
.get("datacenter"):
1515 vim
= myvims
[ sce_vnf
["datacenter"] ]
1516 datacenter_id
= sce_vnf
["datacenter"]
1518 vim
= myvims
[ default_datacenter_id
]
1519 datacenter_id
= default_datacenter_id
1520 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
1521 net_name
= descriptor_net
.get("name")
1523 net_name
= "%s.%s" %(instance_name
, net
["name"])
1524 net_name
= net_name
[:255] #limit length
1525 net_type
= net
['type']
1526 network_id
= vim
.new_network(net_name
, net_type
)
1527 net
['vim_id'] = network_id
1528 if sce_vnf
['uuid'] not in auxNetDict
:
1529 auxNetDict
[sce_vnf
['uuid']] = {}
1530 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1531 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1533 #print "auxNetDict:"
1534 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1536 #3. Creating new vm instances in the VIM
1537 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1538 for sce_vnf
in scenarioDict
['vnfs']:
1539 if sce_vnf
.get("datacenter"):
1540 vim
= myvims
[ sce_vnf
["datacenter"] ]
1541 datacenter_id
= sce_vnf
["datacenter"]
1543 vim
= myvims
[ default_datacenter_id
]
1544 datacenter_id
= default_datacenter_id
1545 sce_vnf
["datacenter_id"] = datacenter_id
1546 sce_vnf
["datacenter_tenant_id"] = vim
['config']['datacenter_tenant_id']
1548 for vm
in sce_vnf
['vms']:
1551 myVMDict
['name'] = "%s.%s.%d" % (instance_name
,sce_vnf
['name'],i
)
1552 myVMDict
['description'] = myVMDict
['name'][0:99]
1554 # myVMDict['start'] = "no"
1555 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1556 #create image at vim in case it not exist
1557 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1558 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
1559 vm
['vim_image_id'] = image_id
1561 #create flavor at vim in case it not exist
1562 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1563 if flavor_dict
['extended']!=None:
1564 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1565 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
1566 vm
['vim_flavor_id'] = flavor_id
1568 myVMDict
['imageRef'] = vm
['vim_image_id']
1569 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1570 myVMDict
['networks'] = []
1571 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
1572 for iface
in vm
['interfaces']:
1574 if iface
['type']=="data":
1575 netDict
['type'] = iface
['model']
1576 elif "model" in iface
and iface
["model"]!=None:
1577 netDict
['model']=iface
['model']
1578 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1579 #discover type of interface looking at flavor
1580 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1581 for flavor_iface
in numa
.get('interfaces',[]):
1582 if flavor_iface
.get('name') == iface
['internal_name']:
1583 if flavor_iface
['dedicated'] == 'yes':
1584 netDict
['type']="PF" #passthrough
1585 elif flavor_iface
['dedicated'] == 'no':
1586 netDict
['type']="VF" #siov
1587 elif flavor_iface
['dedicated'] == 'yes:sriov':
1588 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1589 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1591 netDict
["use"]=iface
['type']
1592 if netDict
["use"]=="data" and not netDict
.get("type"):
1593 #print "netDict", netDict
1594 #print "iface", iface
1595 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'])
1596 if flavor_dict
.get('extended')==None:
1597 raise NfvoException(e_text
+ "After database migration some information is not available. \
1598 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1600 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1601 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1602 netDict
["type"]="virtual"
1603 if "vpci" in iface
and iface
["vpci"] is not None:
1604 netDict
['vpci'] = iface
['vpci']
1605 if "mac" in iface
and iface
["mac"] is not None:
1606 netDict
['mac_address'] = iface
['mac']
1607 netDict
['name'] = iface
['internal_name']
1608 if iface
['net_id'] is None:
1609 for vnf_iface
in sce_vnf
["interfaces"]:
1612 if vnf_iface
['interface_id']==iface
['uuid']:
1613 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
1616 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1617 #skip bridge ifaces not connected to any net
1618 #if 'net_id' not in netDict or netDict['net_id']==None:
1620 myVMDict
['networks'].append(netDict
)
1621 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1622 #print myVMDict['name']
1623 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1624 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1625 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1626 vm_id
= vim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1627 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'], cloud_config
= cloud_config
)
1628 vm
['vim_id'] = vm_id
1629 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1630 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1631 for net
in myVMDict
['networks']:
1633 for iface
in vm
['interfaces']:
1634 if net
["name"]==iface
["internal_name"]:
1635 iface
["vim_id"]=net
["vim_id"]
1637 logger
.debug("create_instance Deployment done")
1638 print yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)
1639 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1640 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
1641 return mydb
.get_instance_scenario(instance_id
)
1642 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
1643 message
= rollback(mydb
, myvims
, rollbackList
)
1644 if isinstance(e
, db_base_Exception
):
1645 error_text
= "database Exception"
1646 elif isinstance(e
, vimconn
.vimconnException
):
1647 error_text
= "VIM Exception"
1649 error_text
= "Exception"
1650 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1651 #logger.error("create_instance: %s", error_text)
1652 raise NfvoException(error_text
, e
.http_code
)
1654 def delete_instance(mydb
, tenant_id
, instance_id
):
1655 #print "Checking that the instance_id exists and getting the instance dictionary"
1656 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
1657 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
1658 tenant_id
= instanceDict
["tenant_id"]
1659 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1661 vims
= get_vim(mydb
, tenant_id
, instanceDict
['datacenter_id'])
1663 logger
.error("!!!!!! nfvo.delete_instance() datacenter not found!!!!")
1666 myvim
= vims
.values()[0]
1667 except NfvoException
as e
:
1668 logger
.error("!!!!!! nfvo.delete_instance() datacenter Exception!!!! " + str(e
))
1672 #1. Delete from Database
1674 #result,c = mydb.delete_row_by_id('instance_scenarios', instance_id, nfvo_tenant)
1675 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
1679 error_msg
= "Not possible to delete VIM VMs and networks. Datacenter not found at database!!!"
1685 for sce_vnf
in instanceDict
['vnfs']:
1688 for vm
in sce_vnf
['vms']:
1690 myvim
.delete_vminstance(vm
['vim_vm_id'])
1691 except vimconn
.vimconnNotFoundException
as e
:
1692 error_msg
+="\n VM id={} not found at VIM".format(vm
['vim_vm_id'])
1693 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
1694 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
1695 except vimconn
.vimconnException
as e
:
1696 error_msg
+="\n Error: " + e
.http_code
+ " VM id=" + vm
['vim_vm_id']
1697 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s': %s",
1698 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
1702 for net
in instanceDict
['nets']:
1704 continue #skip not created nets
1708 myvim
.delete_network(net
['vim_net_id'])
1709 except vimconn
.vimconnNotFoundException
as e
:
1710 error_msg
+="\n NET id={} not found at VIM".format(net
['vim_net_id'])
1711 logger
.warn("NET '%s', VIM id '%s', from VNF_id '%s' not found",
1712 net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'])
1713 except vimconn
.vimconnException
as e
:
1714 error_msg
+="\n Error: " + e
.http_code
+ " Net id=" + net
['vim_vm_id']
1715 logger
.error("Error %d deleting NET '%s', VIM id '%s', from VNF_id '%s': %s",
1716 e
.http_code
, net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'], str(e
))
1717 if len(error_msg
)>0:
1718 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
1720 return 'instance ' + message
+ ' deleted'
1722 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
1723 '''Refreshes a scenario instance. It modifies instanceDict'''
1725 - 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
1728 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
1729 #print "nfvo.refresh_instance begins"
1730 #print json.dumps(instanceDict, indent=4)
1732 #print "Getting the VIM URL and the VIM tenant_id"
1733 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
1735 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
1736 myvim
= vims
.values()[0]
1738 # 1. Getting VIM vm and net list
1739 vms_updated
= [] #List of VM instance uuids in openmano that were updated
1742 for sce_vnf
in instanceDict
['vnfs']:
1743 for vm
in sce_vnf
['vms']:
1744 vm_list
.append(vm
['vim_vm_id'])
1745 vms_notupdated
.append(vm
["uuid"])
1747 nets_updated
= [] #List of VM instance uuids in openmano that were updated
1750 for net
in instanceDict
['nets']:
1751 net_list
.append(net
['vim_net_id'])
1752 nets_notupdated
.append(net
["uuid"])
1755 # 1. Getting the status of all VMs
1756 vm_dict
= myvim
.refresh_vms_status(vm_list
)
1758 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
1759 for sce_vnf
in instanceDict
['vnfs']:
1760 for vm
in sce_vnf
['vms']:
1761 vm_id
= vm
['vim_vm_id']
1762 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
1763 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
1764 has_mgmt_iface
= False
1765 for iface
in vm
["interfaces"]:
1766 if iface
["type"]=="mgmt":
1767 has_mgmt_iface
= True
1768 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
1769 vm_dict
[vm_id
]['status'] = "ACTIVE"
1770 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'):
1771 vm
['status'] = vm_dict
[vm_id
]['status']
1772 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
1773 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
1774 # 2.1. Update in openmano DB the VMs whose status changed
1776 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
1777 vms_notupdated
.remove(vm
["uuid"])
1779 vms_updated
.append(vm
["uuid"])
1780 except db_base_Exception
as e
:
1781 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
1782 # 2.2. Update in openmano DB the interface VMs
1783 for interface
in interfaces
:
1784 #translate from vim_net_id to instance_net_id
1786 for net
in instanceDict
['nets']:
1787 if net
["vim_net_id"] == interface
["vim_net_id"]:
1788 network_id
= net
["uuid"]
1792 del interface
["vim_net_id"]
1794 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
1795 except db_base_Exception
as e
:
1796 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
1798 # 3. Getting the status of all nets
1799 net_dict
= myvim
.refresh_nets_status(net_list
)
1801 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
1802 # TODO: update nets inside a vnf
1803 for net
in instanceDict
['nets']:
1804 net_id
= net
['vim_net_id']
1805 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'):
1806 net
['status'] = net_dict
[net_id
]['status']
1807 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
1808 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
1809 # 5.1. Update in openmano DB the nets whose status changed
1811 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
1812 nets_notupdated
.remove(net
["uuid"])
1814 nets_updated
.append(net
["uuid"])
1815 except db_base_Exception
as e
:
1816 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
1817 except vimconn
.vimconnException
as e
:
1818 #logger.error("VIM exception %s %s", type(e).__name__, str(e))
1819 raise NfvoException(str(e
), e
.http_code
)
1821 # Returns appropriate output
1822 #print "nfvo.refresh_instance finishes"
1823 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
1824 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
1825 instance_id
= instanceDict
['uuid']
1826 if len(vms_notupdated
)+len(nets_notupdated
)>0:
1827 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
1828 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
1830 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
1832 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
1833 #print "Checking that the instance_id exists and getting the instance dictionary"
1834 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
1835 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
1837 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1838 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
1840 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
1841 myvim
= vims
.values()[0]
1844 input_vnfs
= action_dict
.pop("vnfs", [])
1845 input_vms
= action_dict
.pop("vms", [])
1846 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
1850 for sce_vnf
in instanceDict
['vnfs']:
1851 for vm
in sce_vnf
['vms']:
1852 if not action_over_all
:
1853 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
1854 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
1857 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
1858 if "console" in action_dict
:
1859 if not global_config
["http_console_proxy"]:
1860 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
1861 "description": "{protocol}//{ip}:{port}/{suffix}".format(
1862 protocol
=data
["protocol"],
1863 ip
= data
["server"],
1864 port
= data
["port"],
1865 suffix
= data
["suffix"]),
1869 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
1870 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
1871 "description": "this console is only reachable by local interface",
1876 #print "console data", data
1878 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
1879 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
1880 "description": "{protocol}//{ip}:{port}/{suffix}".format(
1881 protocol
=data
["protocol"],
1882 ip
= global_config
["http_console_host"],
1883 port
= console_thread
.port
,
1884 suffix
= data
["suffix"]),
1888 except NfvoException
as e
:
1889 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
1893 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
1895 except vimconn
.vimconnException
as e
:
1896 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
1899 if vm_ok
==0: #all goes wrong
1904 def create_or_use_console_proxy_thread(console_server
, console_port
):
1905 #look for a non-used port
1906 console_thread_key
= console_server
+ ":" + str(console_port
)
1907 if console_thread_key
in global_config
["console_thread"]:
1908 #global_config["console_thread"][console_thread_key].start_timeout()
1909 return global_config
["console_thread"][console_thread_key
]
1911 for port
in global_config
["console_port_iterator"]():
1912 #print "create_or_use_console_proxy_thread() port:", port
1913 if port
in global_config
["console_ports"]:
1916 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
1918 global_config
["console_thread"][console_thread_key
] = clithread
1919 global_config
["console_ports"][port
] = console_thread_key
1921 except cli
.ConsoleProxyExceptionPortUsed
as e
:
1922 #port used, try with onoher
1924 except cli
.ConsoleProxyException
as e
:
1925 raise NfvoException(str(e
), HTTP_Bad_Request
)
1926 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
1928 def check_tenant(mydb
, tenant_id
):
1929 '''check that tenant exists at database'''
1930 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
1932 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
1935 def new_tenant(mydb
, tenant_dict
):
1936 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
1939 def delete_tenant(mydb
, tenant
):
1940 #get nfvo_tenant info
1942 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
1943 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
1944 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
1946 def new_datacenter(mydb
, datacenter_descriptor
):
1947 if "config" in datacenter_descriptor
:
1948 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
1949 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
1950 return datacenter_id
1952 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
1953 #obtain data, check that only one exist
1954 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
1956 datacenter_id
= datacenter
['uuid']
1957 where
={'uuid': datacenter
['uuid']}
1958 if "config" in datacenter_descriptor
:
1959 if datacenter_descriptor
['config']!=None:
1961 new_config_dict
= datacenter_descriptor
["config"]
1964 for k
in new_config_dict
:
1965 if new_config_dict
[k
]==None:
1968 config_dict
= yaml
.load(datacenter
["config"])
1969 config_dict
.update(new_config_dict
)
1973 except Exception as e
:
1974 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
1975 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
1976 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
1977 return datacenter_id
1979 def delete_datacenter(mydb
, datacenter
):
1980 #get nfvo_tenant info
1981 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
1982 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
1983 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
1985 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None):
1986 #get datacenter info
1987 if utils
.check_valid_uuid(datacenter
):
1988 vims
= get_vim(mydb
, datacenter_id
=datacenter
)
1990 vims
= get_vim(mydb
, datacenter_name
=datacenter
)
1992 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
1994 #print "nfvo.datacenter_action() error. Several datacenters found"
1995 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1997 datacenter_id
=vims
.keys()[0]
1998 myvim
=vims
[datacenter_id
]
1999 datacenter_name
=myvim
["name"]
2001 create_vim_tenant
=True if vim_tenant_id
==None and vim_tenant_name
==None else False
2003 #get nfvo_tenant info
2004 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2005 if vim_tenant_name
==None:
2006 vim_tenant_name
=tenant_dict
['name']
2008 #check that this association does not exist before
2009 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2010 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2011 if len(tenants_datacenters
)>0:
2012 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2014 vim_tenant_id_exist_atdb
=False
2015 if not create_vim_tenant
:
2016 where_
={"datacenter_id": datacenter_id
}
2017 if vim_tenant_id
!=None:
2018 where_
["vim_tenant_id"] = vim_tenant_id
2019 if vim_tenant_name
!=None:
2020 where_
["vim_tenant_name"] = vim_tenant_name
2021 #check if vim_tenant_id is already at database
2022 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2023 if len(datacenter_tenants_dict
)>=1:
2024 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2025 vim_tenant_id_exist_atdb
=True
2026 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2028 datacenter_tenants_dict
= {}
2029 #insert at table datacenter_tenants
2030 else: #if vim_tenant_id==None:
2031 #create tenant at VIM if not provided
2033 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2034 except vimconn
.vimconnException
as e
:
2035 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2036 datacenter_tenants_dict
= {}
2037 datacenter_tenants_dict
["created"]="true"
2039 #fill datacenter_tenants table
2040 if not vim_tenant_id_exist_atdb
:
2041 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2042 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2043 datacenter_tenants_dict
["user"] = vim_username
2044 datacenter_tenants_dict
["passwd"] = vim_password
2045 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2046 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2047 datacenter_tenants_dict
["uuid"] = id_
2049 #fill tenants_datacenters table
2050 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2051 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2052 return datacenter_id
2054 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2055 #get datacenter info
2056 if utils
.check_valid_uuid(datacenter
):
2057 vims
= get_vim(mydb
, datacenter_id
=datacenter
)
2059 vims
= get_vim(mydb
, datacenter_name
=datacenter
)
2061 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2063 #print "nfvo.datacenter_action() error. Several datacenters found"
2064 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2065 datacenter_id
=vims
.keys()[0]
2066 myvim
=vims
[datacenter_id
]
2068 #get nfvo_tenant info
2069 if not tenant_id
or tenant_id
=="any":
2072 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2073 tenant_uuid
= tenant_dict
['uuid']
2075 #check that this association exist before
2076 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2078 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2079 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2080 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2081 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2083 #delete this association
2084 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2086 #get vim_tenant info and deletes
2088 for tenant_datacenter_item
in tenant_datacenter_list
:
2089 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2090 #try to delete vim:tenant
2092 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2093 if vim_tenant_dict
['created']=='true':
2094 #delete tenant at VIM if created by NFVO
2096 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2097 except vimconn
.vimconnException
as e
:
2098 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2099 logger
.warn(warning
)
2100 except db_base_Exception
as e
:
2101 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2102 pass #the error will be caused because dependencies, vim_tenant can not be deleted
2104 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2106 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2108 #get datacenter info
2109 if utils
.check_valid_uuid(datacenter
):
2110 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2112 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2114 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2116 #print "nfvo.datacenter_action() error. Several datacenters found"
2117 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2118 datacenter_id
=vims
.keys()[0]
2119 myvim
=vims
[datacenter_id
]
2121 if 'net-update' in action_dict
:
2123 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2125 except vimconn
.vimconnException
as e
:
2126 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2127 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2128 #update nets Change from VIM format to NFVO format
2131 net_nfvo
={'datacenter_id': datacenter_id
}
2132 net_nfvo
['name'] = net
['name']
2133 #net_nfvo['description']= net['name']
2134 net_nfvo
['vim_net_id'] = net
['id']
2135 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2136 net_nfvo
['shared'] = net
['shared']
2137 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2138 net_list
.append(net_nfvo
)
2139 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2140 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2142 elif 'net-edit' in action_dict
:
2143 net
= action_dict
['net-edit'].pop('net')
2144 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2145 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2146 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2148 elif 'net-delete' in action_dict
:
2149 net
= action_dict
['net-deelte'].get('net')
2150 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2151 result
= mydb
.delete_row(FROM
='datacenter_nets',
2152 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2156 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2158 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2159 #get datacenter info
2160 if utils
.check_valid_uuid(datacenter
):
2161 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2163 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2165 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2167 #print "nfvo.datacenter_action() error. Several datacenters found"
2168 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2169 datacenter_id
=vims
.keys()[0]
2171 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2172 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2173 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2176 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2177 #get datacenter info
2178 if utils
.check_valid_uuid(datacenter
):
2179 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2181 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2183 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2185 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2186 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2187 datacenter_id
=vims
.keys()[0]
2188 myvim
=vims
[datacenter_id
]
2191 action_dict
= action_dict
["netmap"]
2192 if 'vim_id' in action_dict
:
2193 filter_dict
["id"] = action_dict
['vim_id']
2194 if 'vim_name' in action_dict
:
2195 filter_dict
["name"] = action_dict
['vim_name']
2197 filter_dict
["shared"] = True
2200 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
2201 except vimconn
.vimconnException
as e
:
2202 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
2203 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2204 if len(vim_nets
)>1 and action_dict
:
2205 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
2206 elif len(vim_nets
)==0: # and action_dict:
2207 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
2209 for net
in vim_nets
:
2210 net_nfvo
={'datacenter_id': datacenter_id
}
2211 if action_dict
and "name" in action_dict
:
2212 net_nfvo
['name'] = action_dict
['name']
2214 net_nfvo
['name'] = net
['name']
2215 #net_nfvo['description']= net['name']
2216 net_nfvo
['vim_net_id'] = net
['id']
2217 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2218 net_nfvo
['shared'] = net
['shared']
2219 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2221 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2222 net_nfvo
["status"] = "OK"
2223 net_nfvo
["uuid"] = net_id
2224 except db_base_Exception
as e
:
2228 net_nfvo
["status"] = "FAIL: " + str(e
)
2229 net_list
.append(net_nfvo
)
2232 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2233 #get datacenter info
2234 if utils
.check_valid_uuid(datacenter
):
2235 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2237 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2239 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2241 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2242 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2243 datacenter_id
=vims
.keys()[0]
2244 myvim
=vims
[datacenter_id
]
2247 if utils
.check_valid_uuid(name
):
2248 filter_dict
["id"] = name
2250 filter_dict
["name"] = name
2252 if item
=="networks":
2253 #filter_dict['tenant_id'] = myvim['tenant_id']
2254 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2255 elif item
=="tenants":
2256 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2258 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2259 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
2260 if name
and len(content
)==1:
2261 return {item
[:-1]: content
[0]}
2262 elif name
and len(content
)==0:
2263 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
2266 return {item
: content
}
2267 except vimconn
.vimconnException
as e
:
2268 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
2269 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
2271 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
2272 #get datacenter info
2273 if tenant_id
== "any":
2276 if utils
.check_valid_uuid(datacenter
):
2277 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2279 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2281 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2283 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2284 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2285 datacenter_id
=vims
.keys()[0]
2286 myvim
=vims
[datacenter_id
]
2288 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2289 logger
.debug("vim_action_delete vim response: " + str(content
))
2290 items
= content
.values()[0]
2291 if type(items
)==list and len(items
)==0:
2292 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
2293 elif type(items
)==list and len(items
)>1:
2294 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
2295 else: # it is a dict
2296 item_id
= items
["id"]
2297 item_name
= str(items
.get("name"))
2300 if item
=="networks":
2301 content
= myvim
.delete_network(item_id
)
2302 elif item
=="tenants":
2303 content
= myvim
.delete_tenant(item_id
)
2305 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2306 except vimconn
.vimconnException
as e
:
2307 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
2308 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
2310 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
2312 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2313 #get datacenter info
2314 print "vim_action_create descriptor", descriptor
2315 if tenant_id
== "any":
2318 if utils
.check_valid_uuid(datacenter
):
2319 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2321 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2323 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2325 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2326 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2327 datacenter_id
=vims
.keys()[0]
2328 myvim
=vims
[datacenter_id
]
2331 if item
=="networks":
2332 net
= descriptor
["network"]
2333 net_name
= net
.pop("name")
2334 net_type
= net
.pop("type", "bridge")
2335 net_public
=net
.pop("shared", False)
2336 content
= myvim
.new_network(net_name
, net_type
, net_public
, **net
)
2337 elif item
=="tenants":
2338 tenant
= descriptor
["tenant"]
2339 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2341 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2342 except vimconn
.vimconnException
as e
:
2343 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
2345 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)