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 result, content:
96 <0, error_text upon error
97 NUMBER, dictionary with datacenter_id: vim_class with these keys:
98 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
101 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
102 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
103 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
104 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
105 if nfvo_tenant
or vim_tenant
:
106 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'
107 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
108 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
111 from_
= 'datacenters as d'
112 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
114 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
117 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
118 if vim
["config"] != None:
119 extra
.update(yaml
.load(vim
["config"]))
120 if vim
["type"] not in vimconn_imported
:
123 module
= "vimconn_" + vim
["type"]
124 module_info
= imp
.find_module(module
)
125 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
126 vimconn_imported
[vim
["type"]] = vim_conn
127 except (IOError, ImportError) as e
:
128 if module_info
and module_info
[0]:
129 file.close(module_info
[0])
130 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
131 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
135 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
136 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
137 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
138 tenant_id
=vim
.get('vim_tenant_id'), tenant_name
=vim
.get('vim_tenant_name'),
139 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
140 user
=vim
.get('user'), passwd
=vim
.get('passwd'),
143 except Exception as e
:
144 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
146 except db_base_Exception
as e
:
147 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
149 def rollback(mydb
, vims
, rollback_list
):
151 #delete things by reverse order
152 for i
in range(len(rollback_list
)-1, -1, -1):
153 item
= rollback_list
[i
]
154 if item
["where"]=="vim":
155 if item
["vim_id"] not in vims
:
157 vim
=vims
[ item
["vim_id"] ]
159 if item
["what"]=="image":
160 vim
.delete_image(item
["uuid"])
161 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
162 elif item
["what"]=="flavor":
163 vim
.delete_flavor(item
["uuid"])
164 mydb
.delete_row(FROM
="datacenters_flavos", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
165 elif item
["what"]=="network":
166 vim
.delete_network(item
["uuid"])
167 elif item
["what"]=="vm":
168 vim
.delete_vminstance(item
["uuid"])
169 except vimconn
.vimconnException
as e
:
170 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
171 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
172 except db_base_Exception
as e
:
173 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
177 if item
["what"]=="image":
178 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
179 elif item
["what"]=="flavor":
180 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
181 except db_base_Exception
as e
:
182 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
183 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
184 if len(undeleted_items
)==0:
185 return True," Rollback successful."
187 return False," Rollback fails to delete: " + str(undeleted_items
)
189 def check_vnf_descriptor(vnf_descriptor
):
191 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
193 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
195 #dataplane interfaces
196 for numa
in vnfc
.get("numas",() ):
197 for interface
in numa
.get("interfaces",()):
198 if interface
["name"] in name_list
:
199 raise NfvoException("Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC"\
200 .format(vnfc
["name"], interface
["name"]),
202 name_list
.append( interface
["name"] )
204 for interface
in vnfc
.get("bridge-ifaces",() ):
205 if interface
["name"] in name_list
:
206 raise NfvoException("Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC"\
207 .format(vnfc
["name"], interface
["name"]),
209 name_list
.append( interface
["name"] )
210 vnfc_interfaces
[ vnfc
["name"] ] = name_list
212 #check if the info in external_connections matches with the one in the vnfcs
214 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
215 if external_connection
["name"] in name_list
:
216 raise NfvoException("Error at vnf:external-connections:name, value '{}' already used as an external-connection"\
217 .format(external_connection
["name"]),
219 name_list
.append(external_connection
["name"])
220 if external_connection
["VNFC"] not in vnfc_interfaces
:
221 raise NfvoException("Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC"\
222 .format(external_connection
["name"], external_connection
["VNFC"]),
225 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
226 raise NfvoException("Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC"\
227 .format(external_connection
["name"], external_connection
["local_iface_name"]),
230 #check if the info in internal_connections matches with the one in the vnfcs
232 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
233 if internal_connection
["name"] in name_list
:
234 raise NfvoException("Error at vnf:internal-connections:name, value '%s' already used as an internal-connection"\
235 .format(internal_connection
["name"]),
237 name_list
.append(internal_connection
["name"])
238 #We should check that internal-connections of type "ptp" have only 2 elements
239 if len(internal_connection
["elements"])>2 and internal_connection
["type"] == "ptp":
240 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements, size must be 2 for a type:'ptp'"\
241 .format(internal_connection
["name"]),
243 for port
in internal_connection
["elements"]:
244 if port
["VNFC"] not in vnfc_interfaces
:
245 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC"\
246 .format(internal_connection
["name"], port
["VNFC"]),
248 if port
["local_iface_name"] not in vnfc_interfaces
[ port
["VNFC"] ]:
249 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC"\
250 .format(internal_connection
["name"], port
["local_iface_name"]),
252 return -HTTP_Bad_Request
,
254 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
256 if only_create_at_vim
:
257 image_mano_id
= image_dict
['uuid']
259 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
261 image_mano_id
= images
[0]['uuid']
264 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
265 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None)
267 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
268 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
269 #create image at every vim
270 for vim_id
,vim
in vims
.iteritems():
271 image_created
="false"
273 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
274 #look at VIM if this image exist
276 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
277 except vimconn
.vimconnNotFoundException
as e
:
278 #Create the image in VIM
280 image_vim_id
= vim
.new_image(image_dict
)
281 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
283 except vimconn
.vimconnException
as e
:
285 logger
.error("Error creating image at VIM: %s", str(e
))
287 image_vim_id
= str(e
)
288 logger
.warn("Error creating image at VIM: %s", str(e
))
290 except vimconn
.vimconnException
as e
:
291 logger
.warn("Error contacting VIM to know if the image exist at VIM: %s", str(e
))
292 image_vim_id
= str(e
)
294 #if reach here the image has been create or exist
296 #add new vim_id at datacenters_images
297 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
298 elif image_db
[0]["vim_id"]!=image_vim_id
:
299 #modify existing vim_id at datacenters_images
300 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
302 return image_vim_id
if only_create_at_vim
else image_mano_id
304 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
305 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
306 'ram':flavor_dict
.get('ram'),
307 'vcpus':flavor_dict
.get('vcpus'),
309 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
310 del flavor_dict
['extended']
311 if 'extended' in flavor_dict
:
312 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
314 #look if flavor exist
315 if only_create_at_vim
:
316 flavor_mano_id
= flavor_dict
['uuid']
318 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
320 flavor_mano_id
= flavors
[0]['uuid']
323 #create one by one the images of aditional disks
324 dev_image_list
=[] #list of images
325 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
327 for device
in flavor_dict
['extended'].get('devices',[]):
328 if "image" not in device
:
330 image_dict
={'location':device
['image'], 'name':flavor_dict
['name']+str(dev_nb
)+"-img", 'description':flavor_dict
.get('description')}
331 image_metadata_dict
= device
.get('image metadata', None)
332 image_metadata_str
= None
333 if image_metadata_dict
!= None:
334 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
335 image_dict
['metadata']=image_metadata_str
336 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
337 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
338 dev_image_list
.append(image_id
)
340 temp_flavor_dict
['name'] = flavor_dict
['name']
341 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
342 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
343 flavor_mano_id
= content
344 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
345 #create flavor at every vim
346 if 'uuid' in flavor_dict
:
347 del flavor_dict
['uuid']
349 for vim_id
,vim
in vims
.items():
350 flavor_created
="false"
352 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
353 #look at VIM if this flavor exist SKIPPED
354 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
356 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
360 #Create the flavor in VIM
361 #Translate images at devices from MANO id to VIM id
362 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
363 #make a copy of original devices
365 for device
in flavor_dict
["extended"].get("devices",[]):
368 devices_original
.append(dev
)
369 if 'image' in device
:
371 if 'image metadata' in device
:
372 del device
['image metadata']
374 for index
in range(0,len(devices_original
)) :
375 device
=devices_original
[index
]
376 if "image" not in device
:
378 image_dict
={'location':device
['image'], 'name':flavor_dict
['name']+str(dev_nb
)+"-img", 'description':flavor_dict
.get('description')}
379 image_metadata_dict
= device
.get('image metadata', None)
380 image_metadata_str
= None
381 if image_metadata_dict
!= None:
382 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
383 image_dict
['metadata']=image_metadata_str
384 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
385 image_dict
["uuid"]=image_mano_id
386 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
387 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
390 #check that this vim_id exist in VIM, if not create
391 flavor_vim_id
=flavor_db
[0]["vim_id"]
393 vim
.get_flavor(flavor_vim_id
)
394 continue #flavor exist
395 except vimconn
.vimconnException
:
397 #create flavor at vim
398 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
400 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
401 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
402 flavor_created
="true"
403 except vimconn
.vimconnException
as e
:
405 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
407 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
409 #if reach here the flavor has been create or exist
410 if len(flavor_db
)==0:
411 #add new vim_id at datacenters_flavors
412 mydb
.new_row('datacenters_flavors', {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
, 'created':flavor_created
})
413 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
414 #modify existing vim_id at datacenters_flavors
415 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
417 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
419 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
422 # Step 1. Check the VNF descriptor
423 check_vnf_descriptor(vnf_descriptor
)
424 # Step 2. Check tenant exist
425 if tenant_id
!= "any":
426 check_tenant(mydb
, tenant_id
)
427 if "tenant_id" in vnf_descriptor
["vnf"]:
428 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
429 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
432 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
433 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
434 vims
= get_vim(mydb
, tenant_id
)
438 # Step 4. Review the descriptor and add missing fields
439 #print vnf_descriptor
440 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
441 vnf_name
= vnf_descriptor
['vnf']['name']
442 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
443 if "physical" in vnf_descriptor
['vnf']:
444 del vnf_descriptor
['vnf']['physical']
445 #print vnf_descriptor
446 # Step 5. Check internal connections
447 # TODO: to be moved to step 1????
448 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
449 for ic
in internal_connections
:
450 if len(ic
['elements'])>2 and ic
['type']=='ptp':
451 raise NfvoException("Mismatch 'type':'ptp' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'data'".format(len(ic
), ic
['name']),
453 elif len(ic
['elements'])==2 and ic
['type']=='data':
454 raise NfvoException("Mismatch 'type':'data' with 2 elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'ptp'".format(ic
['name']),
457 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
458 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
459 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
461 #For each VNFC, we add it to the VNFCDict and we create a flavor.
462 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
463 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
465 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
466 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
468 VNFCitem
["name"] = vnfc
['name']
469 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
471 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
474 myflavorDict
["name"] = vnfc
['name']+"-flv"
475 myflavorDict
["description"] = VNFCitem
["description"]
476 myflavorDict
["ram"] = vnfc
.get("ram", 0)
477 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
478 myflavorDict
["disk"] = vnfc
.get("disk", 1)
479 myflavorDict
["extended"] = {}
481 devices
= vnfc
.get("devices")
483 myflavorDict
["extended"]["devices"] = devices
486 # 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
487 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
489 # Previous code has been commented
490 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
491 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
492 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
493 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
495 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
497 # print "Error creating flavor: unknown processor model. Rollback successful."
498 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
500 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
501 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
503 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
504 myflavorDict
['extended']['numas'] = vnfc
['numas']
508 # Step 6.2 New flavors are created in the VIM
509 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
511 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
512 VNFCitem
["flavor_id"] = flavor_id
513 VNFCDict
[vnfc
['name']] = VNFCitem
515 logger
.debug("Creating new images in the VIM for each VNFC")
516 # Step 6.3 New images are created in the VIM
517 #For each VNFC, we must create the appropriate image.
518 #This "for" loop might be integrated with the previous one
519 #In case this integration is made, the VNFCDict might become a VNFClist.
520 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
521 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
522 image_dict
={'location':vnfc
['VNFC image'], 'name':vnfc
['name']+"-img", 'description':VNFCDict
[vnfc
['name']]['description']}
523 image_metadata_dict
= vnfc
.get('image metadata', None)
524 image_metadata_str
= None
525 if image_metadata_dict
is not None:
526 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
527 image_dict
['metadata']=image_metadata_str
528 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
529 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
530 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
531 VNFCDict
[vnfc
['name']]["image_id"] = image_id
532 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
['VNFC image']
535 # Step 7. Storing the VNF descriptor in the repository
536 if "descriptor" not in vnf_descriptor
["vnf"]:
537 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
539 # Step 8. Adding the VNF to the NFVO DB
540 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
542 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
543 _
, message
= rollback(mydb
, vims
, rollback_list
)
544 if isinstance(e
, db_base_Exception
):
545 error_text
= "Exception at database"
546 elif isinstance(e
, KeyError):
547 error_text
= "KeyError exception "
548 e
.http_code
= HTTP_Internal_Server_Error
550 error_text
= "Exception at VIM"
551 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
552 #logger.error("start_scenario %s", error_text)
553 raise NfvoException(error_text
, e
.http_code
)
555 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
556 #check valid tenant_id
557 check_tenant(mydb
, tenant_id
)
560 if tenant_id
!= "any":
561 where_or
["tenant_id"] = tenant_id
562 where_or
["public"] = True
563 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
566 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
567 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
568 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
569 data
={'vnf' : filtered_content
}
571 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
572 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description'),
573 WHERE
={'vnfs.uuid': vnf_id
} )
575 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
577 data
['vnf']['VNFC'] = content
579 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
580 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
581 WHERE
={'vnfs.uuid': vnf_id
} )
582 data
['vnf']['nets'] = content
584 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
585 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
586 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
587 WHERE
={'vnfs.uuid': vnf_id
},
588 WHERE_NOT
={'interfaces.external_name': None} )
590 data
['vnf']['external-connections'] = content
594 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
596 if tenant_id
!= "any":
597 check_tenant(mydb
, tenant_id
)
598 # Get the URL of the VIM from the nfvo_tenant and the datacenter
599 vims
= get_vim(mydb
, tenant_id
)
603 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
605 if tenant_id
!= "any":
606 where_or
["tenant_id"] = tenant_id
607 where_or
["public"] = True
608 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
611 # "Getting the list of flavors and tenants of the VNF"
612 flavorList
= get_flavorlist(mydb
, vnf_id
)
613 if len(flavorList
)==0:
614 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
616 imageList
= get_imagelist(mydb
, vnf_id
)
617 if len(imageList
)==0:
618 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
620 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
622 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
625 for flavor
in flavorList
:
626 #check if flavor is used by other vnf
628 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
630 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
632 #flavor not used, must be deleted
634 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
636 if flavor_vim
["datacenter_id"] not in vims
:
638 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
640 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
642 myvim
.delete_flavor(flavor_vim
["vim_id"])
643 except vimconn
.vimconnNotFoundException
as e
:
644 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
645 except vimconn
.vimconnException
as e
:
646 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
647 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
648 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
649 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
650 mydb
.delete_row_by_id('flavors', flavor
)
651 except db_base_Exception
as e
:
652 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
653 undeletedItems
.append("flavor %s" % flavor
)
656 for image
in imageList
:
658 #check if image is used by other vnf
659 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
661 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
663 #image not used, must be deleted
665 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
667 if image_vim
["datacenter_id"] not in vims
:
669 if image_vim
['created']=='false': #skip this image because not created by openmano
671 myvim
=vims
[ image_vim
["datacenter_id"] ]
673 myvim
.delete_image(image_vim
["vim_id"])
674 except vimconn
.vimconnNotFoundException
as e
:
675 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
676 except vimconn
.vimconnException
as e
:
677 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
678 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
679 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
680 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
681 mydb
.delete_row_by_id('images', image
)
682 except db_base_Exception
as e
:
683 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
684 undeletedItems
.append("image %s" % image
)
686 return vnf_id
+ " " + vnf
["name"]
688 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
690 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
691 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
695 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
696 myvim
= vims
.values()[0]
697 result
,servers
= myvim
.get_hosts_info()
699 return result
, servers
700 topology
= {'name':myvim
['name'] , 'servers': servers
}
701 return result
, topology
703 def get_hosts(mydb
, nfvo_tenant_id
):
704 vims
= get_vim(mydb
, nfvo_tenant_id
)
706 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
708 #print "nfvo.datacenter_action() error. Several datacenters found"
709 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
710 myvim
= vims
.values()[0]
712 hosts
= myvim
.get_hosts()
713 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
715 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
717 server
={'name':host
['name'], 'vms':[]}
718 for vm
in host
['instances']:
719 #get internal name and model
721 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
722 WHERE
={'vim_vm_id':vm
['id']} )
724 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
726 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
728 except db_base_Exception
as e
:
729 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
730 datacenter
['Datacenters'][0]['servers'].append(server
)
731 #return -400, "en construccion"
733 #print 'datacenters '+ json.dumps(datacenter, indent=4)
735 except vimconn
.vimconnException
as e
:
736 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
738 def new_scenario(mydb
, tenant_id
, topo
):
740 # result, vims = get_vim(mydb, tenant_id)
742 # return result, vims
744 if tenant_id
!= "any":
745 check_tenant(mydb
, tenant_id
)
746 if "tenant_id" in topo
:
747 if topo
["tenant_id"] != tenant_id
:
748 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
753 #1.1: get VNFs and external_networks (other_nets).
755 other_nets
={} #external_networks, bridge_networks and data_networkds
756 nodes
= topo
['topology']['nodes']
757 for k
in nodes
.keys():
758 if nodes
[k
]['type'] == 'VNF':
760 vnfs
[k
]['ifaces'] = {}
761 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
762 other_nets
[k
] = nodes
[k
]
763 other_nets
[k
]['external']=True
764 elif nodes
[k
]['type'] == 'network':
765 other_nets
[k
] = nodes
[k
]
766 other_nets
[k
]['external']=False
769 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
770 for name
,vnf
in vnfs
.items():
772 where_or
={"tenant_id": tenant_id
, 'public': "true"}
774 error_pos
= "'topology':'nodes':'" + name
+ "'"
776 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
777 where
['uuid'] = vnf
['vnf_id']
778 if 'VNF model' in vnf
:
779 error_text
+= " 'VNF model' " + vnf
['VNF model']
780 where
['name'] = vnf
['VNF model']
782 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
784 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
790 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
792 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
793 vnf
['uuid']=vnf_db
[0]['uuid']
794 vnf
['description']=vnf_db
[0]['description']
795 #get external interfaces
796 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
797 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
798 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
799 for ext_iface
in ext_ifaces
:
800 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
802 #1.4 get list of connections
803 conections
= topo
['topology']['connections']
805 for k
in conections
.keys():
806 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
807 ifaces_list
= conections
[k
]['nodes'].items()
808 elif type(conections
[k
]['nodes'])==list: #list with dictionary
810 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
811 for k2
in conection_pair_list
:
814 con_type
= conections
[k
].get("type", "link")
815 if con_type
!= "link":
817 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
818 other_nets
[k
] = {'external': False}
819 if conections
[k
].get("graph"):
820 other_nets
[k
]["graph"] = conections
[k
]["graph"]
821 ifaces_list
.append( (k
, None) )
824 if con_type
== "external_network":
825 other_nets
[k
]['external'] = True
826 if conections
[k
].get("model"):
827 other_nets
[k
]["model"] = conections
[k
]["model"]
829 other_nets
[k
]["model"] = k
830 if con_type
== "dataplane_net" or con_type
== "bridge_net":
831 other_nets
[k
]["model"] = con_type
834 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)
835 #print set(ifaces_list)
836 #check valid VNF and iface names
837 for iface
in ifaces_list
:
838 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
839 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
840 str(k
), iface
[0]), HTTP_Not_Found
)
841 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
842 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
843 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
845 #1.5 unify connections from the pair list to a consolidated list
847 while index
< len(conections_list
):
849 while index2
< len(conections_list
):
850 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
851 conections_list
[index
] |
= conections_list
[index2
]
852 del conections_list
[index2
]
855 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
857 #for k in conections_list:
862 #1.6 Delete non external nets
863 # for k in other_nets.keys():
864 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
865 # for con in conections_list:
867 # for index in range(0,len(con)):
868 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
869 # for index in delete_indexes:
872 #1.7: Check external_ports are present at database table datacenter_nets
873 for k
,net
in other_nets
.items():
874 error_pos
= "'topology':'nodes':'" + k
+ "'"
875 if net
['external']==False:
876 if 'name' not in net
:
878 if 'model' not in net
:
879 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
880 if net
['model']=='bridge_net':
881 net
['type']='bridge';
882 elif net
['model']=='dataplane_net':
885 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
887 #IF we do not want to check that external network exist at datacenter
892 # if 'net_id' in net:
893 # error_text += " 'net_id' " + net['net_id']
894 # WHERE_['uuid'] = net['net_id']
896 # error_text += " 'model' " + net['model']
897 # WHERE_['name'] = net['model']
898 # if len(WHERE_) == 0:
899 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
900 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
901 # FROM='datacenter_nets', WHERE=WHERE_ )
903 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
905 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
906 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
908 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
909 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
910 # other_nets[k].update(net_db[0])
913 net_nb
=0 #Number of nets
914 for con
in conections_list
:
915 #check if this is connected to a external net
919 for index
in range(0,len(con
)):
920 #check if this is connected to a external net
921 for net_key
in other_nets
.keys():
922 if con
[index
][0]==net_key
:
923 if other_net_index
>=0:
924 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
925 #print "nfvo.new_scenario " + error_text
926 raise NfvoException(error_text
, HTTP_Bad_Request
)
928 other_net_index
= index
931 #print "other_net_index", other_net_index
933 if other_net_index
>=0:
934 del con
[other_net_index
]
935 #IF we do not want to check that external network exist at datacenter
936 if other_nets
[net_target
]['external'] :
937 if "name" not in other_nets
[net_target
]:
938 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
939 if other_nets
[net_target
]["type"] == "external_network":
940 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
941 other_nets
[net_target
]["type"] = "data"
943 other_nets
[net_target
]["type"] = "bridge"
945 # if other_nets[net_target]['external'] :
946 # 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
947 # if type_=='data' and other_nets[net_target]['type']=="ptp":
948 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
949 # print "nfvo.new_scenario " + error_text
950 # return -HTTP_Bad_Request, error_text
953 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
956 net_type_bridge
=False
958 net_target
= "__-__net"+str(net_nb
)
959 net_list
[net_target
] = {'name': "net-"+str(net_nb
), 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
962 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
963 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
964 if iface_type
=='mgmt' or iface_type
=='bridge':
965 net_type_bridge
= True
968 if net_type_bridge
and net_type_data
:
969 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
970 #print "nfvo.new_scenario " + error_text
971 raise NfvoException(error_text
, HTTP_Bad_Request
)
972 elif net_type_bridge
:
975 type_
='data' if len(con
)>2 else 'ptp'
976 net_list
[net_target
]['type'] = type_
979 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
980 #print "nfvo.new_scenario " + error_text
982 raise NfvoException(error_text
, HTTP_Bad_Request
)
984 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
985 #1.8.1 obtain management net
986 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
987 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
988 #1.8.2 check all interfaces from all vnfs
991 for vnf
in vnfs
.values():
992 for iface
in vnf
['ifaces'].values():
993 if iface
['type']=='mgmt' and 'net_key' not in iface
:
995 iface
['net_key'] = 'mgmt'
997 if add_mgmt_net
and 'mgmt' not in net_list
:
998 net_list
['mgmt']=mgmt_net
[0]
999 net_list
['mgmt']['external']=True
1000 net_list
['mgmt']['graph']={'visible':False}
1002 net_list
.update(other_nets
)
1004 #print 'net_list', net_list
1009 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1010 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1011 'tenant_id':tenant_id
, 'name':topo
['name'],
1012 'description':topo
.get('description',topo
['name']),
1013 'public': topo
.get('public', False)
1018 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
):
1019 scenario
= scenario_dict
["scenario"]
1020 if tenant_id
!= "any":
1021 check_tenant(mydb
, tenant_id
)
1022 if "tenant_id" in scenario
:
1023 if scenario
["tenant_id"] != tenant_id
:
1024 print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1025 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1026 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1030 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1031 for name
,vnf
in scenario
["vnfs"].iteritems():
1033 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1035 error_pos
= "'topology':'nodes':'" + name
+ "'"
1037 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1038 where
['uuid'] = vnf
['vnf_id']
1039 if 'vnf_name' in vnf
:
1040 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1041 where
['name'] = vnf
['vnf_name']
1043 raise NfvoException("Needed a 'vnf_id' or 'VNF model' at " + error_pos
, HTTP_Bad_Request
)
1044 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1050 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1052 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1053 vnf
['uuid']=vnf_db
[0]['uuid']
1054 vnf
['description']=vnf_db
[0]['description']
1056 #get external interfaces
1057 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1058 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1059 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1060 for ext_iface
in ext_ifaces
:
1061 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1063 #2: Insert net_key at every vnf interface
1064 for net_name
,net
in scenario
["networks"].iteritems():
1065 net_type_bridge
=False
1067 for iface_dict
in net
["interfaces"]:
1068 for vnf
,iface
in iface_dict
.iteritems():
1069 if vnf
not in scenario
["vnfs"]:
1070 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1071 #print "nfvo.new_scenario_v02 " + error_text
1072 raise NfvoException(error_text
, HTTP_Not_Found
)
1073 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1074 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1075 #print "nfvo.new_scenario_v02 " + error_text
1076 raise NfvoException(error_text
, HTTP_Bad_Request
)
1077 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1078 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1079 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1080 #print "nfvo.new_scenario_v02 " + error_text
1081 raise NfvoException(error_text
, HTTP_Bad_Request
)
1082 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1083 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1084 if iface_type
=='mgmt' or iface_type
=='bridge':
1085 net_type_bridge
= True
1087 net_type_data
= True
1088 if net_type_bridge
and net_type_data
:
1089 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1090 #print "nfvo.new_scenario " + error_text
1091 raise NfvoException(error_text
, HTTP_Bad_Request
)
1092 elif net_type_bridge
:
1095 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1097 net
['name'] = net_name
1098 net
['external'] = net
.get('external', False)
1100 #3: insert at database
1101 scenario
["nets"] = scenario
["networks"]
1102 scenario
['tenant_id'] = tenant_id
1103 scenario_id
= mydb
.new_scenario( scenario
)
1106 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1107 data
["uuid"] = scenario_id
1108 data
["tenant_id"] = tenant_id
1109 c
= mydb
.edit_scenario( data
)
1112 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1113 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1114 datacenter_id
= None
1115 datacenter_name
=None
1116 if datacenter
!= None:
1117 if utils
.check_valid_uuid(datacenter
):
1118 datacenter_id
= datacenter
1120 datacenter_name
= datacenter
1121 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
)
1123 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
1125 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
1126 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1127 myvim
= vims
.values()[0]
1128 myvim_tenant
= myvim
['tenant_id']
1129 datacenter_id
= myvim
['id']
1130 datacenter_name
= myvim
['name']
1131 datacenter_tenant_id
= myvim
['config']['datacenter_tenant_id']
1134 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1135 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1136 scenarioDict
['datacenter_tenant_id'] = datacenter_tenant_id
1137 scenarioDict
['datacenter_id'] = datacenter_id
1138 #print '================scenarioDict======================='
1139 #print json.dumps(scenarioDict, indent=4)
1140 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1142 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1143 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1145 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1146 auxNetDict
['scenario'] = {}
1148 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1149 for sce_net
in scenarioDict
['nets']:
1150 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1152 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1153 myNetName
= myNetName
[0:255] #limit length
1154 myNetType
= sce_net
['type']
1156 myNetDict
["name"] = myNetName
1157 myNetDict
["type"] = myNetType
1158 myNetDict
["tenant_id"] = myvim_tenant
1160 #We should use the dictionary as input parameter for new_network
1162 if not sce_net
["external"]:
1163 network_id
= myvim
.new_network(myNetName
, myNetType
)
1164 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1165 sce_net
['vim_id'] = network_id
1166 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1167 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1169 if sce_net
['vim_id'] == None:
1170 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1171 _
, message
= rollback(mydb
, vims
, rollbackList
)
1172 logger
.error("nfvo.start_scenario: %s", error_text
)
1173 raise NfvoException(error_text
, HTTP_Bad_Request
)
1174 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1175 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1177 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1178 #For each vnf net, we create it and we add it to instanceNetlist.
1179 for sce_vnf
in scenarioDict
['vnfs']:
1180 for net
in sce_vnf
['nets']:
1181 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1183 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1184 myNetName
= myNetName
[0:255] #limit length
1185 myNetType
= net
['type']
1187 myNetDict
["name"] = myNetName
1188 myNetDict
["type"] = myNetType
1189 myNetDict
["tenant_id"] = myvim_tenant
1192 #We should use the dictionary as input parameter for new_network
1193 network_id
= myvim
.new_network(myNetName
, myNetType
)
1194 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1195 net
['vim_id'] = network_id
1196 if sce_vnf
['uuid'] not in auxNetDict
:
1197 auxNetDict
[sce_vnf
['uuid']] = {}
1198 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1199 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1201 #print "auxNetDict:"
1202 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1204 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1205 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1207 for sce_vnf
in scenarioDict
['vnfs']:
1208 for vm
in sce_vnf
['vms']:
1211 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1212 myVMDict
['name'] = "%s.%s.%d" % (instance_scenario_name
,sce_vnf
['name'],i
)
1213 #myVMDict['description'] = vm['description']
1214 myVMDict
['description'] = myVMDict
['name'][0:99]
1216 myVMDict
['start'] = "no"
1217 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1218 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1220 #create image at vim in case it not exist
1221 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1222 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1223 vm
['vim_image_id'] = image_id
1225 #create flavor at vim in case it not exist
1226 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1227 if flavor_dict
['extended']!=None:
1228 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1229 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1230 vm
['vim_flavor_id'] = flavor_id
1233 myVMDict
['imageRef'] = vm
['vim_image_id']
1234 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1235 myVMDict
['networks'] = []
1236 for iface
in vm
['interfaces']:
1238 if iface
['type']=="data":
1239 netDict
['type'] = iface
['model']
1240 elif "model" in iface
and iface
["model"]!=None:
1241 netDict
['model']=iface
['model']
1242 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1243 #discover type of interface looking at flavor
1244 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1245 for flavor_iface
in numa
.get('interfaces',[]):
1246 if flavor_iface
.get('name') == iface
['internal_name']:
1247 if flavor_iface
['dedicated'] == 'yes':
1248 netDict
['type']="PF" #passthrough
1249 elif flavor_iface
['dedicated'] == 'no':
1250 netDict
['type']="VF" #siov
1251 elif flavor_iface
['dedicated'] == 'yes:sriov':
1252 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1253 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1255 netDict
["use"]=iface
['type']
1256 if netDict
["use"]=="data" and not netDict
.get("type"):
1257 #print "netDict", netDict
1258 #print "iface", iface
1259 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'])
1260 if flavor_dict
.get('extended')==None:
1261 raise NfvoException(e_text
+ "After database migration some information is not available. \
1262 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1264 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1265 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1266 netDict
["type"]="virtual"
1267 if "vpci" in iface
and iface
["vpci"] is not None:
1268 netDict
['vpci'] = iface
['vpci']
1269 if "mac" in iface
and iface
["mac"] is not None:
1270 netDict
['mac_address'] = iface
['mac']
1271 netDict
['name'] = iface
['internal_name']
1272 if iface
['net_id'] is None:
1273 for vnf_iface
in sce_vnf
["interfaces"]:
1276 if vnf_iface
['interface_id']==iface
['uuid']:
1277 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1280 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1281 #skip bridge ifaces not connected to any net
1282 #if 'net_id' not in netDict or netDict['net_id']==None:
1284 myVMDict
['networks'].append(netDict
)
1285 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1286 #print myVMDict['name']
1287 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1288 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1289 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1290 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1291 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1292 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1293 vm
['vim_id'] = vm_id
1294 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1295 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1296 for net
in myVMDict
['networks']:
1298 for iface
in vm
['interfaces']:
1299 if net
["name"]==iface
["internal_name"]:
1300 iface
["vim_id"]=net
["vim_id"]
1303 logger
.debug("start scenario Deployment done")
1304 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1305 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1306 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1307 return mydb
.get_instance_scenario(instance_id
)
1309 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1310 _
, message
= rollback(mydb
, vims
, rollbackList
)
1311 if isinstance(e
, db_base_Exception
):
1312 error_text
= "Exception at database"
1314 error_text
= "Exception at VIM"
1315 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1316 #logger.error("start_scenario %s", error_text)
1317 raise NfvoException(error_text
, e
.http_code
)
1319 def create_instance(mydb
, tenant_id
, instance_dict
):
1320 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1321 logger
.debug("Creating instance...")
1322 scenario
= instance_dict
["scenario"]
1323 datacenter_id
= None
1324 datacenter_name
=None
1325 datacenter
= instance_dict
.get("datacenter")
1327 if utils
.check_valid_uuid(datacenter
):
1328 datacenter_id
= datacenter
1330 datacenter_name
= datacenter
1331 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
=None)
1333 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
1335 #print "nfvo.datacenter_action() error. Several datacenters found"
1336 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1337 myvim
= vims
.values()[0]
1338 #myvim_tenant = myvim['tenant_id']
1339 datacenter_id
= myvim
['id']
1340 datacenter_name
= myvim
['name']
1341 datacenter_tenant_id
= myvim
['config']['datacenter_tenant_id']
1344 #print "Checking that the scenario exists and getting the scenario dictionary"
1345 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_id
)
1346 scenarioDict
['datacenter_tenant_id'] = datacenter_tenant_id
1347 scenarioDict
['datacenter_id'] = datacenter_id
1349 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1350 auxNetDict
['scenario'] = {}
1352 #print "scenario dict: ",yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1353 instance_name
= instance_dict
["name"]
1354 instance_description
= instance_dict
.get("description")
1356 #0 check correct parameters
1357 for descriptor_net
in instance_dict
.get("networks",{}).keys():
1359 for scenario_net
in scenarioDict
['nets']:
1360 if descriptor_net
== scenario_net
["name"]:
1364 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(descriptor_net
), HTTP_Bad_Request
)
1365 for descriptor_vnf
in instance_dict
.get("vnfs",{}).keys():
1367 for scenario_vnf
in scenarioDict
['vnfs']:
1368 if descriptor_vnf
== scenario_vnf
['name']:
1372 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(descriptor_vnf
), HTTP_Bad_Request
)
1374 #1. Creating new nets (sce_nets) in the VIM"
1375 for sce_net
in scenarioDict
['nets']:
1376 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
1377 net_name
= descriptor_net
.get("name")
1378 net_type
= sce_net
['type']
1379 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
1380 if sce_net
["external"]:
1382 net_name
= sce_net
["name"]
1383 if "netmap-use" in descriptor_net
or "netmap-create" in descriptor_net
:
1384 create_network
= False
1385 lookfor_network
= False
1386 if "netmap-use" in descriptor_net
:
1387 lookfor_network
= True
1388 if utils
.check_valid_uuid(descriptor_net
["netmap-use"]):
1389 filter_text
= "scenario id '%s'" % descriptor_net
["netmap-use"]
1390 lookfor_filter
["id"] = descriptor_net
["netmap-use"]
1392 filter_text
= "scenario name '%s'" % descriptor_net
["netmap-use"]
1393 lookfor_filter
["name"] = descriptor_net
["netmap-use"]
1394 if "netmap-create" in descriptor_net
:
1395 create_network
= True
1396 net_vim_name
= net_name
1397 if descriptor_net
["netmap-create"]:
1398 net_vim_name
= descriptor_net
["netmap-create"]
1400 elif sce_net
['vim_id'] != None:
1401 #there is a netmap at datacenter_nets database
1402 create_network
= False
1403 lookfor_network
= True
1404 lookfor_filter
["id"] = sce_net
['vim_id']
1405 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
1406 #look for network at datacenter and return error
1408 #There is not a netmap, look at datacenter for a net with this name and create if not found
1409 create_network
= True
1410 lookfor_network
= True
1411 lookfor_filter
["name"] = sce_net
["name"]
1412 net_vim_name
= sce_net
["name"]
1413 filter_text
= "scenario name '%s'" % sce_net
["name"]
1416 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
1417 net_name
= net_name
[:255] #limit length
1418 net_vim_name
= net_name
1419 create_network
= True
1420 lookfor_network
= False
1423 vim_nets
= myvim
.get_network_list(filter_dict
=lookfor_filter
)
1424 if len(vim_nets
) > 1:
1425 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1426 elif len(vim_nets
) == 0:
1427 if not create_network
:
1428 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1430 sce_net
['vim_id'] = vim_nets
[0]['id']
1431 auxNetDict
['scenario'][sce_net
['uuid']] = vim_nets
[0]['id']
1432 create_network
= False
1434 #if network is not external
1435 network_id
= myvim
.new_network(net_vim_name
, net_type
)
1436 sce_net
['vim_id'] = network_id
1437 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1438 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1440 #2. Creating new nets (vnf internal nets) in the VIM"
1441 #For each vnf net, we create it and we add it to instanceNetlist.
1442 for sce_vnf
in scenarioDict
['vnfs']:
1443 for net
in sce_vnf
['nets']:
1444 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
1445 net_name
= descriptor_net
.get("name")
1447 net_name
= "%s.%s" %(instance_name
, net
["name"])
1448 net_name
= net_name
[:255] #limit length
1449 net_type
= net
['type']
1450 network_id
= myvim
.new_network(net_name
, net_type
)
1451 net
['vim_id'] = network_id
1452 if sce_vnf
['uuid'] not in auxNetDict
:
1453 auxNetDict
[sce_vnf
['uuid']] = {}
1454 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1455 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1457 #print "auxNetDict:"
1458 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1460 #3. Creating new vm instances in the VIM
1461 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1462 for sce_vnf
in scenarioDict
['vnfs']:
1464 for vm
in sce_vnf
['vms']:
1467 myVMDict
['name'] = "%s.%s.%d" % (instance_name
,sce_vnf
['name'],i
)
1468 myVMDict
['description'] = myVMDict
['name'][0:99]
1470 # myVMDict['start'] = "no"
1471 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1472 #create image at vim in case it not exist
1473 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1474 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1475 vm
['vim_image_id'] = image_id
1477 #create flavor at vim in case it not exist
1478 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1479 if flavor_dict
['extended']!=None:
1480 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1481 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, rollbackList
, True)
1482 vm
['vim_flavor_id'] = flavor_id
1484 myVMDict
['imageRef'] = vm
['vim_image_id']
1485 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1486 myVMDict
['networks'] = []
1487 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
1488 for iface
in vm
['interfaces']:
1490 if iface
['type']=="data":
1491 netDict
['type'] = iface
['model']
1492 elif "model" in iface
and iface
["model"]!=None:
1493 netDict
['model']=iface
['model']
1494 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1495 #discover type of interface looking at flavor
1496 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1497 for flavor_iface
in numa
.get('interfaces',[]):
1498 if flavor_iface
.get('name') == iface
['internal_name']:
1499 if flavor_iface
['dedicated'] == 'yes':
1500 netDict
['type']="PF" #passthrough
1501 elif flavor_iface
['dedicated'] == 'no':
1502 netDict
['type']="VF" #siov
1503 elif flavor_iface
['dedicated'] == 'yes:sriov':
1504 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1505 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1507 netDict
["use"]=iface
['type']
1508 if netDict
["use"]=="data" and not netDict
.get("type"):
1509 #print "netDict", netDict
1510 #print "iface", iface
1511 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'])
1512 if flavor_dict
.get('extended')==None:
1513 raise NfvoException(e_text
+ "After database migration some information is not available. \
1514 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1516 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1517 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1518 netDict
["type"]="virtual"
1519 if "vpci" in iface
and iface
["vpci"] is not None:
1520 netDict
['vpci'] = iface
['vpci']
1521 if "mac" in iface
and iface
["mac"] is not None:
1522 netDict
['mac_address'] = iface
['mac']
1523 netDict
['name'] = iface
['internal_name']
1524 if iface
['net_id'] is None:
1525 for vnf_iface
in sce_vnf
["interfaces"]:
1528 if vnf_iface
['interface_id']==iface
['uuid']:
1529 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1532 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1533 #skip bridge ifaces not connected to any net
1534 #if 'net_id' not in netDict or netDict['net_id']==None:
1536 myVMDict
['networks'].append(netDict
)
1537 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1538 #print myVMDict['name']
1539 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1540 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1541 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1542 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1543 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1544 vm
['vim_id'] = vm_id
1545 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1546 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1547 for net
in myVMDict
['networks']:
1549 for iface
in vm
['interfaces']:
1550 if net
["name"]==iface
["internal_name"]:
1551 iface
["vim_id"]=net
["vim_id"]
1553 logger
.debug("create_instance Deployment done")
1554 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1555 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1556 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
1557 return mydb
.get_instance_scenario(instance_id
)
1558 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
1559 message
= rollback(mydb
, vims
, rollbackList
)
1560 if isinstance(e
, db_base_Exception
):
1561 error_text
= "database Exception"
1562 elif isinstance(e
, vimconn
.vimconnException
):
1563 error_text
= "VIM Exception"
1565 error_text
= "Exception"
1566 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1567 #logger.error("create_instance: %s", error_text)
1568 raise NfvoException(error_text
, e
.http_code
)
1570 def delete_instance(mydb
, tenant_id
, instance_id
):
1571 #print "Checking that the instance_id exists and getting the instance dictionary"
1572 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
1573 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
1574 tenant_id
= instanceDict
["tenant_id"]
1575 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1577 vims
= get_vim(mydb
, tenant_id
, instanceDict
['datacenter_id'])
1579 logger
.error("!!!!!! nfvo.delete_instance() datacenter not found!!!!")
1582 myvim
= vims
.values()[0]
1583 except NfvoException
as e
:
1584 logger
.error("!!!!!! nfvo.delete_instance() datacenter Exception!!!! " + str(e
))
1588 #1. Delete from Database
1590 #result,c = mydb.delete_row_by_id('instance_scenarios', instance_id, nfvo_tenant)
1591 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
1595 error_msg
= "Not possible to delete VIM VMs and networks. Datacenter not found at database!!!"
1601 for sce_vnf
in instanceDict
['vnfs']:
1604 for vm
in sce_vnf
['vms']:
1606 myvim
.delete_vminstance(vm
['vim_vm_id'])
1607 except vimconn
.vimconnNotFoundException
as e
:
1608 error_msg
+="\n VM id={} not found at VIM".format(vm
['vim_vm_id'])
1609 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
1610 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
1611 except vimconn
.vimconnException
as e
:
1612 error_msg
+="\n Error: " + e
.http_code
+ " VM id=" + vm
['vim_vm_id']
1613 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s': %s",
1614 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
1618 for net
in instanceDict
['nets']:
1620 continue #skip not created nets
1624 myvim
.delete_network(net
['vim_net_id'])
1625 except vimconn
.vimconnNotFoundException
as e
:
1626 error_msg
+="\n NET id={} not found at VIM".format(net
['vim_net_id'])
1627 logger
.warn("NET '%s', VIM id '%s', from VNF_id '%s' not found",
1628 net
['uuid'], vm
['vim_net_id'], sce_vnf
['vnf_id'])
1629 except vimconn
.vimconnException
as e
:
1630 error_msg
+="\n Error: " + e
.http_code
+ " Net id=" + net
['vim_vm_id']
1631 logger
.error("Error %d deleting NET '%s', VIM id '%s', from VNF_id '%s': %s",
1632 e
.http_code
, net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'], str(e
))
1633 if len(error_msg
)>0:
1634 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
1636 return 'instance ' + message
+ ' deleted'
1638 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
1639 '''Refreshes a scenario instance. It modifies instanceDict'''
1641 - 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
1644 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
1645 #print "nfvo.refresh_instance begins"
1646 #print json.dumps(instanceDict, indent=4)
1648 #print "Getting the VIM URL and the VIM tenant_id"
1649 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
1651 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
1652 myvim
= vims
.values()[0]
1654 # 1. Getting VIM vm and net list
1655 vms_updated
= [] #List of VM instance uuids in openmano that were updated
1658 for sce_vnf
in instanceDict
['vnfs']:
1659 for vm
in sce_vnf
['vms']:
1660 vm_list
.append(vm
['vim_vm_id'])
1661 vms_notupdated
.append(vm
["uuid"])
1663 nets_updated
= [] #List of VM instance uuids in openmano that were updated
1666 for net
in instanceDict
['nets']:
1667 net_list
.append(net
['vim_net_id'])
1668 nets_notupdated
.append(net
["uuid"])
1671 # 1. Getting the status of all VMs
1672 vm_dict
= myvim
.refresh_vms_status(vm_list
)
1674 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
1675 for sce_vnf
in instanceDict
['vnfs']:
1676 for vm
in sce_vnf
['vms']:
1677 vm_id
= vm
['vim_vm_id']
1678 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
1679 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
1680 has_mgmt_iface
= False
1681 for iface
in vm
["interfaces"]:
1682 if iface
["type"]=="mgmt":
1683 has_mgmt_iface
= True
1684 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
1685 vm_dict
[vm_id
]['status'] = "ACTIVE"
1686 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'):
1687 vm
['status'] = vm_dict
[vm_id
]['status']
1688 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
1689 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
1690 # 2.1. Update in openmano DB the VMs whose status changed
1692 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
1693 vms_notupdated
.remove(vm
["uuid"])
1695 vms_updated
.append(vm
["uuid"])
1696 except db_base_Exception
as e
:
1697 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
1698 # 2.2. Update in openmano DB the interface VMs
1699 for interface
in interfaces
:
1700 #translate from vim_net_id to instance_net_id
1702 for net
in instanceDict
['nets']:
1703 if net
["vim_net_id"] == interface
["vim_net_id"]:
1704 network_id
= net
["uuid"]
1708 del interface
["vim_net_id"]
1710 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
1711 except db_base_Exception
as e
:
1712 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
1714 # 3. Getting the status of all nets
1715 net_dict
= myvim
.refresh_nets_status(net_list
)
1717 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
1718 # TODO: update nets inside a vnf
1719 for net
in instanceDict
['nets']:
1720 net_id
= net
['vim_net_id']
1721 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'):
1722 net
['status'] = net_dict
[net_id
]['status']
1723 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
1724 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
1725 # 5.1. Update in openmano DB the nets whose status changed
1727 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
1728 nets_notupdated
.remove(net
["uuid"])
1730 nets_updated
.append(net
["uuid"])
1731 except db_base_Exception
as e
:
1732 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
1733 except vimconn
.vimconnException
as e
:
1734 #logger.error("VIM exception %s %s", type(e).__name__, str(e))
1735 raise NfvoException(str(e
), e
.http_code
)
1737 # Returns appropriate output
1738 #print "nfvo.refresh_instance finishes"
1739 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
1740 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
1741 instance_id
= instanceDict
['uuid']
1742 if len(vms_notupdated
)+len(nets_notupdated
)>0:
1743 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
1744 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
1746 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
1748 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
1749 #print "Checking that the instance_id exists and getting the instance dictionary"
1750 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
1751 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
1753 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1754 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
1756 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
1757 myvim
= vims
.values()[0]
1760 input_vnfs
= action_dict
.pop("vnfs", [])
1761 input_vms
= action_dict
.pop("vms", [])
1762 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
1766 for sce_vnf
in instanceDict
['vnfs']:
1767 for vm
in sce_vnf
['vms']:
1768 if not action_over_all
:
1769 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
1770 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
1773 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
1774 if "console" in action_dict
:
1775 if not global_config
["http_console_proxy"]:
1776 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
1777 "description": "{protocol}//{ip}:{port}/{suffix}".format(
1778 protocol
=data
["protocol"],
1779 ip
= data
["server"],
1780 port
= data
["port"],
1781 suffix
= data
["suffix"]),
1785 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
1786 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
1787 "description": "this console is only reachable by local interface",
1792 #print "console data", data
1794 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
1795 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
1796 "description": "{protocol}//{ip}:{port}/{suffix}".format(
1797 protocol
=data
["protocol"],
1798 ip
= global_config
["http_console_host"],
1799 port
= console_thread
.port
,
1800 suffix
= data
["suffix"]),
1804 except NfvoException
as e
:
1805 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
1809 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
1811 except vimconn
.vimconnException
as e
:
1812 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
1815 if vm_ok
==0: #all goes wrong
1820 def create_or_use_console_proxy_thread(console_server
, console_port
):
1821 #look for a non-used port
1822 console_thread_key
= console_server
+ ":" + str(console_port
)
1823 if console_thread_key
in global_config
["console_thread"]:
1824 #global_config["console_thread"][console_thread_key].start_timeout()
1825 return global_config
["console_thread"][console_thread_key
]
1827 for port
in global_config
["console_port_iterator"]():
1828 #print "create_or_use_console_proxy_thread() port:", port
1829 if port
in global_config
["console_ports"]:
1832 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
1834 global_config
["console_thread"][console_thread_key
] = clithread
1835 global_config
["console_ports"][port
] = console_thread_key
1837 except cli
.ConsoleProxyExceptionPortUsed
as e
:
1838 #port used, try with onoher
1840 except cli
.ConsoleProxyException
as e
:
1841 raise NfvoException(str(e
), HTTP_Bad_Request
)
1842 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
1844 def check_tenant(mydb
, tenant_id
):
1845 '''check that tenant exists at database'''
1846 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
1848 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
1851 def new_tenant(mydb
, tenant_dict
):
1852 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
1855 def delete_tenant(mydb
, tenant
):
1856 #get nfvo_tenant info
1858 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
1859 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
1860 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
1862 def new_datacenter(mydb
, datacenter_descriptor
):
1863 if "config" in datacenter_descriptor
:
1864 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
1865 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
1866 return datacenter_id
1868 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
1869 #obtain data, check that only one exist
1870 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
1872 datacenter_id
= datacenter
['uuid']
1873 where
={'uuid': datacenter
['uuid']}
1874 if "config" in datacenter_descriptor
:
1875 if datacenter_descriptor
['config']!=None:
1877 new_config_dict
= datacenter_descriptor
["config"]
1880 for k
in new_config_dict
:
1881 if new_config_dict
[k
]==None:
1884 config_dict
= yaml
.load(datacenter
["config"])
1885 config_dict
.update(new_config_dict
)
1889 except Exception as e
:
1890 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
1891 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
1892 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
1893 return datacenter_id
1895 def delete_datacenter(mydb
, datacenter
):
1896 #get nfvo_tenant info
1897 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
1898 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
1899 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
1901 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None):
1902 #get datacenter info
1903 if utils
.check_valid_uuid(datacenter
):
1904 vims
= get_vim(mydb
, datacenter_id
=datacenter
)
1906 vims
= get_vim(mydb
, datacenter_name
=datacenter
)
1908 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
1910 #print "nfvo.datacenter_action() error. Several datacenters found"
1911 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1913 datacenter_id
=vims
.keys()[0]
1914 myvim
=vims
[datacenter_id
]
1915 datacenter_name
=myvim
["name"]
1917 create_vim_tenant
=True if vim_tenant_id
==None and vim_tenant_name
==None else False
1919 #get nfvo_tenant info
1920 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
1921 if vim_tenant_name
==None:
1922 vim_tenant_name
=tenant_dict
['name']
1924 #check that this association does not exist before
1925 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
1926 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
1927 if len(tenants_datacenters
)>0:
1928 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
1930 vim_tenant_id_exist_atdb
=False
1931 if not create_vim_tenant
:
1932 where_
={"datacenter_id": datacenter_id
}
1933 if vim_tenant_id
!=None:
1934 where_
["vim_tenant_id"] = vim_tenant_id
1935 if vim_tenant_name
!=None:
1936 where_
["vim_tenant_name"] = vim_tenant_name
1937 #check if vim_tenant_id is already at database
1938 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
1939 if len(datacenter_tenants_dict
)>=1:
1940 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
1941 vim_tenant_id_exist_atdb
=True
1942 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
1944 datacenter_tenants_dict
= {}
1945 #insert at table datacenter_tenants
1946 else: #if vim_tenant_id==None:
1947 #create tenant at VIM if not provided
1949 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
1950 except vimconn
.vimconnException
as e
:
1951 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
1952 datacenter_tenants_dict
= {}
1953 datacenter_tenants_dict
["created"]="true"
1955 #fill datacenter_tenants table
1956 if not vim_tenant_id_exist_atdb
:
1957 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
1958 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
1959 datacenter_tenants_dict
["user"] = vim_username
1960 datacenter_tenants_dict
["passwd"] = vim_password
1961 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
1962 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
1963 datacenter_tenants_dict
["uuid"] = id_
1965 #fill tenants_datacenters table
1966 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
1967 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
1968 return datacenter_id
1970 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
1971 #get datacenter info
1972 if utils
.check_valid_uuid(datacenter
):
1973 vims
= get_vim(mydb
, datacenter_id
=datacenter
)
1975 vims
= get_vim(mydb
, datacenter_name
=datacenter
)
1977 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
1979 #print "nfvo.datacenter_action() error. Several datacenters found"
1980 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1981 datacenter_id
=vims
.keys()[0]
1982 myvim
=vims
[datacenter_id
]
1984 #get nfvo_tenant info
1985 if not tenant_id
or tenant_id
=="any":
1988 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
1989 tenant_uuid
= tenant_dict
['uuid']
1991 #check that this association exist before
1992 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
1994 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
1995 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
1996 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
1997 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
1999 #delete this association
2000 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2002 #get vim_tenant info and deletes
2004 for tenant_datacenter_item
in tenant_datacenter_list
:
2005 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2006 #try to delete vim:tenant
2008 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2009 if vim_tenant_dict
['created']=='true':
2010 #delete tenant at VIM if created by NFVO
2012 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2013 except vimconn
.vimconnException
as e
:
2014 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2015 logger
.warn(warning
)
2016 except db_base_Exception
as e
:
2017 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2018 pass #the error will be caused because dependencies, vim_tenant can not be deleted
2020 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2022 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2024 #get datacenter info
2025 if utils
.check_valid_uuid(datacenter
):
2026 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2028 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2030 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2032 #print "nfvo.datacenter_action() error. Several datacenters found"
2033 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2034 datacenter_id
=vims
.keys()[0]
2035 myvim
=vims
[datacenter_id
]
2037 if 'net-update' in action_dict
:
2039 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2041 except vimconn
.vimconnException
as e
:
2042 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2043 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2044 #update nets Change from VIM format to NFVO format
2047 net_nfvo
={'datacenter_id': datacenter_id
}
2048 net_nfvo
['name'] = net
['name']
2049 #net_nfvo['description']= net['name']
2050 net_nfvo
['vim_net_id'] = net
['id']
2051 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2052 net_nfvo
['shared'] = net
['shared']
2053 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2054 net_list
.append(net_nfvo
)
2055 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2056 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2058 elif 'net-edit' in action_dict
:
2059 net
= action_dict
['net-edit'].pop('net')
2060 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2061 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2062 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2064 elif 'net-delete' in action_dict
:
2065 net
= action_dict
['net-deelte'].get('net')
2066 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2067 result
= mydb
.delete_row(FROM
='datacenter_nets',
2068 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2072 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2074 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2075 #get datacenter info
2076 if utils
.check_valid_uuid(datacenter
):
2077 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2079 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2081 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2083 #print "nfvo.datacenter_action() error. Several datacenters found"
2084 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2085 datacenter_id
=vims
.keys()[0]
2087 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2088 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2089 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2092 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2093 #get datacenter info
2094 if utils
.check_valid_uuid(datacenter
):
2095 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2097 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2099 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2101 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2102 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2103 datacenter_id
=vims
.keys()[0]
2104 myvim
=vims
[datacenter_id
]
2107 action_dict
= action_dict
["netmap"]
2108 if 'vim_id' in action_dict
:
2109 filter_dict
["id"] = action_dict
['vim_id']
2110 if 'vim_name' in action_dict
:
2111 filter_dict
["name"] = action_dict
['vim_name']
2113 filter_dict
["shared"] = True
2116 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
2117 except vimconn
.vimconnException
as e
:
2118 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
2119 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2120 if len(vim_nets
)>1 and action_dict
:
2121 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
2122 elif len(vim_nets
)==0: # and action_dict:
2123 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
2125 for net
in vim_nets
:
2126 net_nfvo
={'datacenter_id': datacenter_id
}
2127 if action_dict
and "name" in action_dict
:
2128 net_nfvo
['name'] = action_dict
['name']
2130 net_nfvo
['name'] = net
['name']
2131 #net_nfvo['description']= net['name']
2132 net_nfvo
['vim_net_id'] = net
['id']
2133 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2134 net_nfvo
['shared'] = net
['shared']
2135 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2137 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2138 net_nfvo
["status"] = "OK"
2139 net_nfvo
["uuid"] = net_id
2140 except db_base_Exception
as e
:
2144 net_nfvo
["status"] = "FAIL: " + str(e
)
2145 net_list
.append(net_nfvo
)
2148 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2149 #get datacenter info
2150 if utils
.check_valid_uuid(datacenter
):
2151 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2153 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2155 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2157 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2158 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2159 datacenter_id
=vims
.keys()[0]
2160 myvim
=vims
[datacenter_id
]
2163 if utils
.check_valid_uuid(name
):
2164 filter_dict
["id"] = name
2166 filter_dict
["name"] = name
2168 if item
=="networks":
2169 #filter_dict['tenant_id'] = myvim['tenant_id']
2170 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2171 elif item
=="tenants":
2172 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2174 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2175 logger
.debug("vim_action response ", content
) #update nets Change from VIM format to NFVO format
2176 if name
and len(content
)==1:
2177 return {item
[:-1]: content
[0]}
2178 elif name
and len(content
)==0:
2179 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
2182 return {item
: content
}
2183 except vimconn
.vimconnException
as e
:
2184 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
2185 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
2187 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
2188 #get datacenter info
2189 if tenant_id
== "any":
2192 if utils
.check_valid_uuid(datacenter
):
2193 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2195 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2197 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2199 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2200 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2201 datacenter_id
=vims
.keys()[0]
2202 myvim
=vims
[datacenter_id
]
2204 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2205 logger
.debug("vim_action_delete vim response: " + str(content
))
2206 items
= content
.values()[0]
2207 if type(items
)==list and len(items
)==0:
2208 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
2209 elif type(items
)==list and len(items
)>1:
2210 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
2211 else: # it is a dict
2212 item_id
= items
["id"]
2213 item_name
= str(items
.get("name"))
2216 if item
=="networks":
2217 content
= myvim
.delete_network(item_id
)
2218 elif item
=="tenants":
2219 content
= myvim
.delete_tenant(item_id
)
2221 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2222 except vimconn
.vimconnException
as e
:
2223 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
2224 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
2226 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
2228 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2229 #get datacenter info
2230 print "vim_action_create descriptor", descriptor
2231 if tenant_id
== "any":
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 item
=="networks":
2248 net
= descriptor
["network"]
2249 net_name
= net
.pop("name")
2250 net_type
= net
.pop("type", "bridge")
2251 net_public
=net
.pop("shared", False)
2252 content
= myvim
.new_network(net_name
, net_type
, net_public
, **net
)
2253 elif item
=="tenants":
2254 tenant
= descriptor
["tenant"]
2255 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2257 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2258 except vimconn
.vimconnException
as e
:
2259 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
2261 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)