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():
773 error_pos
= "'topology':'nodes':'" + name
+ "'"
775 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
776 WHERE_
['uuid'] = vnf
['vnf_id']
777 if 'VNF model' in vnf
:
778 error_text
+= " 'VNF model' " + vnf
['VNF model']
779 WHERE_
['name'] = vnf
['VNF model']
781 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
783 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'), FROM
='vnfs', WHERE
=WHERE_
)
785 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
787 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
788 vnf
['uuid']=vnf_db
[0]['uuid']
789 vnf
['description']=vnf_db
[0]['description']
790 #get external interfaces
791 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
792 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
793 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
794 for ext_iface
in ext_ifaces
:
795 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
797 #1.4 get list of connections
798 conections
= topo
['topology']['connections']
800 for k
in conections
.keys():
801 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
802 ifaces_list
= conections
[k
]['nodes'].items()
803 elif type(conections
[k
]['nodes'])==list: #list with dictionary
805 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
806 for k2
in conection_pair_list
:
809 con_type
= conections
[k
].get("type", "link")
810 if con_type
!= "link":
812 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
813 other_nets
[k
] = {'external': False}
814 if conections
[k
].get("graph"):
815 other_nets
[k
]["graph"] = conections
[k
]["graph"]
816 ifaces_list
.append( (k
, None) )
819 if con_type
== "external_network":
820 other_nets
[k
]['external'] = True
821 if conections
[k
].get("model"):
822 other_nets
[k
]["model"] = conections
[k
]["model"]
824 other_nets
[k
]["model"] = k
825 if con_type
== "dataplane_net" or con_type
== "bridge_net":
826 other_nets
[k
]["model"] = con_type
829 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)
830 #print set(ifaces_list)
831 #check valid VNF and iface names
832 for iface
in ifaces_list
:
833 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
834 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
835 str(k
), iface
[0]), HTTP_Not_Found
)
836 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
837 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
838 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
840 #1.5 unify connections from the pair list to a consolidated list
842 while index
< len(conections_list
):
844 while index2
< len(conections_list
):
845 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
846 conections_list
[index
] |
= conections_list
[index2
]
847 del conections_list
[index2
]
850 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
852 #for k in conections_list:
857 #1.6 Delete non external nets
858 # for k in other_nets.keys():
859 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
860 # for con in conections_list:
862 # for index in range(0,len(con)):
863 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
864 # for index in delete_indexes:
867 #1.7: Check external_ports are present at database table datacenter_nets
868 for k
,net
in other_nets
.items():
869 error_pos
= "'topology':'nodes':'" + k
+ "'"
870 if net
['external']==False:
871 if 'name' not in net
:
873 if 'model' not in net
:
874 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
875 if net
['model']=='bridge_net':
876 net
['type']='bridge';
877 elif net
['model']=='dataplane_net':
880 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
882 #IF we do not want to check that external network exist at datacenter
887 # if 'net_id' in net:
888 # error_text += " 'net_id' " + net['net_id']
889 # WHERE_['uuid'] = net['net_id']
891 # error_text += " 'model' " + net['model']
892 # WHERE_['name'] = net['model']
893 # if len(WHERE_) == 0:
894 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
895 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
896 # FROM='datacenter_nets', WHERE=WHERE_ )
898 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
900 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
901 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
903 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
904 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
905 # other_nets[k].update(net_db[0])
908 net_nb
=0 #Number of nets
909 for con
in conections_list
:
910 #check if this is connected to a external net
914 for index
in range(0,len(con
)):
915 #check if this is connected to a external net
916 for net_key
in other_nets
.keys():
917 if con
[index
][0]==net_key
:
918 if other_net_index
>=0:
919 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
920 #print "nfvo.new_scenario " + error_text
921 raise NfvoException(error_text
, HTTP_Bad_Request
)
923 other_net_index
= index
926 #print "other_net_index", other_net_index
928 if other_net_index
>=0:
929 del con
[other_net_index
]
930 #IF we do not want to check that external network exist at datacenter
931 if other_nets
[net_target
]['external'] :
932 if "name" not in other_nets
[net_target
]:
933 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
934 if other_nets
[net_target
]["type"] == "external_network":
935 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
936 other_nets
[net_target
]["type"] = "data"
938 other_nets
[net_target
]["type"] = "bridge"
940 # if other_nets[net_target]['external'] :
941 # 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
942 # if type_=='data' and other_nets[net_target]['type']=="ptp":
943 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
944 # print "nfvo.new_scenario " + error_text
945 # return -HTTP_Bad_Request, error_text
948 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
951 net_type_bridge
=False
953 net_target
= "__-__net"+str(net_nb
)
954 net_list
[net_target
] = {'name': "net-"+str(net_nb
), 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
957 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
958 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
959 if iface_type
=='mgmt' or iface_type
=='bridge':
960 net_type_bridge
= True
963 if net_type_bridge
and net_type_data
:
964 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
965 #print "nfvo.new_scenario " + error_text
966 raise NfvoException(error_text
, HTTP_Bad_Request
)
967 elif net_type_bridge
:
970 type_
='data' if len(con
)>2 else 'ptp'
971 net_list
[net_target
]['type'] = type_
974 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
975 #print "nfvo.new_scenario " + error_text
977 raise NfvoException(error_text
, HTTP_Bad_Request
)
979 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
980 #1.8.1 obtain management net
981 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
982 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
983 #1.8.2 check all interfaces from all vnfs
986 for vnf
in vnfs
.values():
987 for iface
in vnf
['ifaces'].values():
988 if iface
['type']=='mgmt' and 'net_key' not in iface
:
990 iface
['net_key'] = 'mgmt'
992 if add_mgmt_net
and 'mgmt' not in net_list
:
993 net_list
['mgmt']=mgmt_net
[0]
994 net_list
['mgmt']['external']=True
995 net_list
['mgmt']['graph']={'visible':False}
997 net_list
.update(other_nets
)
999 #print 'net_list', net_list
1004 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1005 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1006 'tenant_id':tenant_id
, 'name':topo
['name'],
1007 'description':topo
.get('description',topo
['name']),
1008 'public': topo
.get('public', False)
1013 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
):
1014 scenario
= scenario_dict
["scenario"]
1015 if tenant_id
!= "any":
1016 check_tenant(mydb
, tenant_id
)
1017 if "tenant_id" in scenario
:
1018 if scenario
["tenant_id"] != tenant_id
:
1019 print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1020 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1021 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1025 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1026 for name
,vnf
in scenario
["vnfs"].iteritems():
1029 error_pos
= "'topology':'nodes':'" + name
+ "'"
1031 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1032 WHERE_
['uuid'] = vnf
['vnf_id']
1033 if 'vnf_name' in vnf
:
1034 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1035 WHERE_
['name'] = vnf
['vnf_name']
1036 if len(WHERE_
) == 0:
1037 raise NfvoException("Needed a 'vnf_id' or 'VNF model' at " + error_pos
, HTTP_Bad_Request
)
1038 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'), FROM
='vnfs', WHERE
=WHERE_
)
1040 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1042 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1043 vnf
['uuid']=vnf_db
[0]['uuid']
1044 vnf
['description']=vnf_db
[0]['description']
1046 #get external interfaces
1047 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1048 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1049 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1050 for ext_iface
in ext_ifaces
:
1051 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1053 #2: Insert net_key at every vnf interface
1054 for net_name
,net
in scenario
["networks"].iteritems():
1055 net_type_bridge
=False
1057 for iface_dict
in net
["interfaces"]:
1058 for vnf
,iface
in iface_dict
.iteritems():
1059 if vnf
not in scenario
["vnfs"]:
1060 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1061 #print "nfvo.new_scenario_v02 " + error_text
1062 raise NfvoException(error_text
, HTTP_Not_Found
)
1063 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1064 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1065 #print "nfvo.new_scenario_v02 " + error_text
1066 raise NfvoException(error_text
, HTTP_Bad_Request
)
1067 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1068 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1069 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1070 #print "nfvo.new_scenario_v02 " + error_text
1071 raise NfvoException(error_text
, HTTP_Bad_Request
)
1072 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1073 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1074 if iface_type
=='mgmt' or iface_type
=='bridge':
1075 net_type_bridge
= True
1077 net_type_data
= True
1078 if net_type_bridge
and net_type_data
:
1079 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1080 #print "nfvo.new_scenario " + error_text
1081 raise NfvoException(error_text
, HTTP_Bad_Request
)
1082 elif net_type_bridge
:
1085 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1087 net
['name'] = net_name
1088 net
['external'] = net
.get('external', False)
1090 #3: insert at database
1091 scenario
["nets"] = scenario
["networks"]
1092 scenario
['tenant_id'] = tenant_id
1093 scenario_id
= mydb
.new_scenario( scenario
)
1096 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1097 data
["uuid"] = scenario_id
1098 data
["tenant_id"] = tenant_id
1099 c
= mydb
.edit_scenario( data
)
1102 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1103 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1104 datacenter_id
= None
1105 datacenter_name
=None
1106 if datacenter
!= None:
1107 if utils
.check_valid_uuid(datacenter
):
1108 datacenter_id
= datacenter
1110 datacenter_name
= datacenter
1111 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
)
1113 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
1115 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
1116 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1117 myvim
= vims
.values()[0]
1118 myvim_tenant
= myvim
['tenant_id']
1119 datacenter_id
= myvim
['id']
1120 datacenter_name
= myvim
['name']
1121 datacenter_tenant_id
= myvim
['config']['datacenter_tenant_id']
1124 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1125 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1126 scenarioDict
['datacenter_tenant_id'] = datacenter_tenant_id
1127 scenarioDict
['datacenter_id'] = datacenter_id
1128 #print '================scenarioDict======================='
1129 #print json.dumps(scenarioDict, indent=4)
1130 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1132 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1133 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1135 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1136 auxNetDict
['scenario'] = {}
1138 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1139 for sce_net
in scenarioDict
['nets']:
1140 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1142 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1143 myNetName
= myNetName
[0:255] #limit length
1144 myNetType
= sce_net
['type']
1146 myNetDict
["name"] = myNetName
1147 myNetDict
["type"] = myNetType
1148 myNetDict
["tenant_id"] = myvim_tenant
1150 #We should use the dictionary as input parameter for new_network
1152 if not sce_net
["external"]:
1153 network_id
= myvim
.new_network(myNetName
, myNetType
)
1154 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1155 sce_net
['vim_id'] = network_id
1156 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1157 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1159 if sce_net
['vim_id'] == None:
1160 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1161 _
, message
= rollback(mydb
, vims
, rollbackList
)
1162 logger
.error("nfvo.start_scenario: %s", error_text
)
1163 raise NfvoException(error_text
, HTTP_Bad_Request
)
1164 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1165 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1167 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1168 #For each vnf net, we create it and we add it to instanceNetlist.
1169 for sce_vnf
in scenarioDict
['vnfs']:
1170 for net
in sce_vnf
['nets']:
1171 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1173 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1174 myNetName
= myNetName
[0:255] #limit length
1175 myNetType
= net
['type']
1177 myNetDict
["name"] = myNetName
1178 myNetDict
["type"] = myNetType
1179 myNetDict
["tenant_id"] = myvim_tenant
1182 #We should use the dictionary as input parameter for new_network
1183 network_id
= myvim
.new_network(myNetName
, myNetType
)
1184 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1185 net
['vim_id'] = network_id
1186 if sce_vnf
['uuid'] not in auxNetDict
:
1187 auxNetDict
[sce_vnf
['uuid']] = {}
1188 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1189 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1191 #print "auxNetDict:"
1192 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1194 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1195 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1197 for sce_vnf
in scenarioDict
['vnfs']:
1198 for vm
in sce_vnf
['vms']:
1201 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1202 myVMDict
['name'] = "%s.%s.%d" % (instance_scenario_name
,sce_vnf
['name'],i
)
1203 #myVMDict['description'] = vm['description']
1204 myVMDict
['description'] = myVMDict
['name'][0:99]
1206 myVMDict
['start'] = "no"
1207 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1208 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1210 #create image at vim in case it not exist
1211 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1212 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1213 vm
['vim_image_id'] = image_id
1215 #create flavor at vim in case it not exist
1216 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1217 if flavor_dict
['extended']!=None:
1218 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1219 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1220 vm
['vim_flavor_id'] = flavor_id
1223 myVMDict
['imageRef'] = vm
['vim_image_id']
1224 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1225 myVMDict
['networks'] = []
1226 for iface
in vm
['interfaces']:
1228 if iface
['type']=="data":
1229 netDict
['type'] = iface
['model']
1230 elif "model" in iface
and iface
["model"]!=None:
1231 netDict
['model']=iface
['model']
1232 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1233 #discover type of interface looking at flavor
1234 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1235 for flavor_iface
in numa
.get('interfaces',[]):
1236 if flavor_iface
.get('name') == iface
['internal_name']:
1237 if flavor_iface
['dedicated'] == 'yes':
1238 netDict
['type']="PF" #passthrough
1239 elif flavor_iface
['dedicated'] == 'no':
1240 netDict
['type']="VF" #siov
1241 elif flavor_iface
['dedicated'] == 'yes:sriov':
1242 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1243 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1245 netDict
["use"]=iface
['type']
1246 if netDict
["use"]=="data" and not netDict
.get("type"):
1247 #print "netDict", netDict
1248 #print "iface", iface
1249 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'])
1250 if flavor_dict
.get('extended')==None:
1251 raise NfvoException(e_text
+ "After database migration some information is not available. \
1252 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1254 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1255 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1256 netDict
["type"]="virtual"
1257 if "vpci" in iface
and iface
["vpci"] is not None:
1258 netDict
['vpci'] = iface
['vpci']
1259 if "mac" in iface
and iface
["mac"] is not None:
1260 netDict
['mac_address'] = iface
['mac']
1261 netDict
['name'] = iface
['internal_name']
1262 if iface
['net_id'] is None:
1263 for vnf_iface
in sce_vnf
["interfaces"]:
1266 if vnf_iface
['interface_id']==iface
['uuid']:
1267 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1270 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1271 #skip bridge ifaces not connected to any net
1272 #if 'net_id' not in netDict or netDict['net_id']==None:
1274 myVMDict
['networks'].append(netDict
)
1275 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1276 #print myVMDict['name']
1277 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1278 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1279 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1280 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1281 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1282 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1283 vm
['vim_id'] = vm_id
1284 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1285 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1286 for net
in myVMDict
['networks']:
1288 for iface
in vm
['interfaces']:
1289 if net
["name"]==iface
["internal_name"]:
1290 iface
["vim_id"]=net
["vim_id"]
1293 logger
.debug("start scenario Deployment done")
1294 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1295 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1296 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1297 return mydb
.get_instance_scenario(instance_id
)
1299 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1300 _
, message
= rollback(mydb
, vims
, rollbackList
)
1301 if isinstance(e
, db_base_Exception
):
1302 error_text
= "Exception at database"
1304 error_text
= "Exception at VIM"
1305 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1306 #logger.error("start_scenario %s", error_text)
1307 raise NfvoException(error_text
, e
.http_code
)
1309 def create_instance(mydb
, tenant_id
, instance_dict
):
1310 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1311 scenario
= instance_dict
["scenario"]
1312 datacenter_id
= None
1313 datacenter_name
=None
1314 datacenter
= instance_dict
.get("datacenter")
1316 if utils
.check_valid_uuid(datacenter
):
1317 datacenter_id
= datacenter
1319 datacenter_name
= datacenter
1320 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
=None)
1322 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
1324 #print "nfvo.datacenter_action() error. Several datacenters found"
1325 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1326 myvim
= vims
.values()[0]
1327 #myvim_tenant = myvim['tenant_id']
1328 datacenter_id
= myvim
['id']
1329 datacenter_name
= myvim
['name']
1330 datacenter_tenant_id
= myvim
['config']['datacenter_tenant_id']
1333 #print "Checking that the scenario exists and getting the scenario dictionary"
1334 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_id
)
1335 scenarioDict
['datacenter_tenant_id'] = datacenter_tenant_id
1336 scenarioDict
['datacenter_id'] = datacenter_id
1338 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1339 auxNetDict
['scenario'] = {}
1341 #print "scenario dict: ",yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1342 instance_name
= instance_dict
["name"]
1343 instance_description
= instance_dict
.get("description")
1345 #0 check correct parameters
1346 for descriptor_net
in instance_dict
.get("networks",{}).keys():
1348 for scenario_net
in scenarioDict
['nets']:
1349 if descriptor_net
== scenario_net
["name"]:
1353 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(descriptor_net
), HTTP_Bad_Request
)
1354 for descriptor_vnf
in instance_dict
.get("vnfs",{}).keys():
1356 for scenario_vnf
in scenarioDict
['vnfs']:
1357 if descriptor_vnf
== scenario_vnf
['name']:
1361 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(descriptor_vnf
), HTTP_Bad_Request
)
1363 #1. Creating new nets (sce_nets) in the VIM"
1364 for sce_net
in scenarioDict
['nets']:
1365 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
1366 net_name
= descriptor_net
.get("name")
1367 net_type
= sce_net
['type']
1368 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
1369 if sce_net
["external"]:
1371 net_name
= sce_net
["name"]
1372 if "netmap-use" in descriptor_net
or "netmap-create" in descriptor_net
:
1373 create_network
= False
1374 lookfor_network
= False
1375 if "netmap-use" in descriptor_net
:
1376 lookfor_network
= True
1377 if utils
.check_valid_uuid(descriptor_net
["netmap-use"]):
1378 filter_text
= "scenario id '%s'" % descriptor_net
["netmap-use"]
1379 lookfor_filter
["id"] = descriptor_net
["netmap-use"]
1381 filter_text
= "scenario name '%s'" % descriptor_net
["netmap-use"]
1382 lookfor_filter
["name"] = descriptor_net
["netmap-use"]
1383 if "netmap-create" in descriptor_net
:
1384 create_network
= True
1385 net_vim_name
= net_name
1386 if descriptor_net
["netmap-create"]:
1387 net_vim_name
= descriptor_net
["netmap-create"]
1389 elif sce_net
['vim_id'] != None:
1390 #there is a netmap at datacenter_nets database
1391 create_network
= False
1392 lookfor_network
= True
1393 lookfor_filter
["id"] = sce_net
['vim_id']
1394 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
1395 #look for network at datacenter and return error
1397 #There is not a netmap, look at datacenter for a net with this name and create if not found
1398 create_network
= True
1399 lookfor_network
= True
1400 lookfor_filter
["name"] = sce_net
["name"]
1401 net_vim_name
= sce_net
["name"]
1402 filter_text
= "scenario name '%s'" % sce_net
["name"]
1405 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
1406 net_name
= net_name
[:255] #limit length
1407 net_vim_name
= net_name
1408 create_network
= True
1409 lookfor_network
= False
1412 vim_nets
= myvim
.get_network_list(filter_dict
=lookfor_filter
)
1413 if len(vim_nets
) > 1:
1414 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1415 elif len(vim_nets
) == 0:
1416 if not create_network
:
1417 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1419 sce_net
['vim_id'] = vim_nets
[0]['id']
1420 auxNetDict
['scenario'][sce_net
['uuid']] = vim_nets
[0]['id']
1421 create_network
= False
1423 #if network is not external
1424 network_id
= myvim
.new_network(net_vim_name
, net_type
)
1425 sce_net
['vim_id'] = network_id
1426 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1427 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1429 #2. Creating new nets (vnf internal nets) in the VIM"
1430 #For each vnf net, we create it and we add it to instanceNetlist.
1431 for sce_vnf
in scenarioDict
['vnfs']:
1432 for net
in sce_vnf
['nets']:
1433 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
1434 net_name
= descriptor_net
.get("name")
1436 net_name
= "%s.%s" %(instance_name
, net
["name"])
1437 net_name
= net_name
[:255] #limit length
1438 net_type
= net
['type']
1439 network_id
= myvim
.new_network(net_name
, net_type
)
1440 net
['vim_id'] = network_id
1441 if sce_vnf
['uuid'] not in auxNetDict
:
1442 auxNetDict
[sce_vnf
['uuid']] = {}
1443 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1444 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1446 #print "auxNetDict:"
1447 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1449 #3. Creating new vm instances in the VIM
1450 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1451 for sce_vnf
in scenarioDict
['vnfs']:
1453 for vm
in sce_vnf
['vms']:
1456 myVMDict
['name'] = "%s.%s.%d" % (instance_name
,sce_vnf
['name'],i
)
1457 myVMDict
['description'] = myVMDict
['name'][0:99]
1459 # myVMDict['start'] = "no"
1460 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1461 #create image at vim in case it not exist
1462 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1463 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1464 vm
['vim_image_id'] = image_id
1466 #create flavor at vim in case it not exist
1467 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1468 if flavor_dict
['extended']!=None:
1469 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1470 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, rollbackList
, True)
1471 vm
['vim_flavor_id'] = flavor_id
1473 myVMDict
['imageRef'] = vm
['vim_image_id']
1474 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1475 myVMDict
['networks'] = []
1476 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
1477 for iface
in vm
['interfaces']:
1479 if iface
['type']=="data":
1480 netDict
['type'] = iface
['model']
1481 elif "model" in iface
and iface
["model"]!=None:
1482 netDict
['model']=iface
['model']
1483 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1484 #discover type of interface looking at flavor
1485 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1486 for flavor_iface
in numa
.get('interfaces',[]):
1487 if flavor_iface
.get('name') == iface
['internal_name']:
1488 if flavor_iface
['dedicated'] == 'yes':
1489 netDict
['type']="PF" #passthrough
1490 elif flavor_iface
['dedicated'] == 'no':
1491 netDict
['type']="VF" #siov
1492 elif flavor_iface
['dedicated'] == 'yes:sriov':
1493 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1494 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1496 netDict
["use"]=iface
['type']
1497 if netDict
["use"]=="data" and not netDict
.get("type"):
1498 #print "netDict", netDict
1499 #print "iface", iface
1500 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'])
1501 if flavor_dict
.get('extended')==None:
1502 raise NfvoException(e_text
+ "After database migration some information is not available. \
1503 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1505 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1506 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1507 netDict
["type"]="virtual"
1508 if "vpci" in iface
and iface
["vpci"] is not None:
1509 netDict
['vpci'] = iface
['vpci']
1510 if "mac" in iface
and iface
["mac"] is not None:
1511 netDict
['mac_address'] = iface
['mac']
1512 netDict
['name'] = iface
['internal_name']
1513 if iface
['net_id'] is None:
1514 for vnf_iface
in sce_vnf
["interfaces"]:
1517 if vnf_iface
['interface_id']==iface
['uuid']:
1518 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1521 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1522 #skip bridge ifaces not connected to any net
1523 #if 'net_id' not in netDict or netDict['net_id']==None:
1525 myVMDict
['networks'].append(netDict
)
1526 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1527 #print myVMDict['name']
1528 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1529 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1530 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1531 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1532 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1533 vm
['vim_id'] = vm_id
1534 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1535 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1536 for net
in myVMDict
['networks']:
1538 for iface
in vm
['interfaces']:
1539 if net
["name"]==iface
["internal_name"]:
1540 iface
["vim_id"]=net
["vim_id"]
1542 logger
.debug("create_instance Deployment done")
1543 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1544 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1545 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
1546 return mydb
.get_instance_scenario(instance_id
)
1547 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
1548 message
= rollback(mydb
, vims
, rollbackList
)
1549 if isinstance(e
, db_base_Exception
):
1550 error_text
= "database Exception"
1551 elif isinstance(e
, vimconn
.vimconnException
):
1552 error_text
= "VIM Exception"
1554 error_text
= "Exception"
1555 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1556 #logger.error("create_instance: %s", error_text)
1557 raise NfvoException(error_text
, e
.http_code
)
1559 def delete_instance(mydb
, tenant_id
, instance_id
):
1560 #print "Checking that the instance_id exists and getting the instance dictionary"
1561 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
1562 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
1563 tenant_id
= instanceDict
["tenant_id"]
1564 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1566 vims
= get_vim(mydb
, tenant_id
, instanceDict
['datacenter_id'])
1568 logger
.error("!!!!!! nfvo.delete_instance() datacenter not found!!!!")
1571 myvim
= vims
.values()[0]
1572 except NfvoException
as e
:
1573 logger
.error("!!!!!! nfvo.delete_instance() datacenter Exception!!!! " + str(e
))
1577 #1. Delete from Database
1579 #result,c = mydb.delete_row_by_id('instance_scenarios', instance_id, nfvo_tenant)
1580 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
1584 error_msg
= "Not possible to delete VIM VMs and networks. Datacenter not found at database!!!"
1590 for sce_vnf
in instanceDict
['vnfs']:
1593 for vm
in sce_vnf
['vms']:
1595 myvim
.delete_vminstance(vm
['vim_vm_id'])
1596 except vimconn
.vimconnNotFoundException
as e
:
1597 error_msg
+="\n VM id={} not found at VIM".format(vm
['vim_vm_id'])
1598 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
1599 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
1600 except vimconn
.vimconnException
as e
:
1601 error_msg
+="\n Error: " + e
.http_code
+ " VM id=" + vm
['vim_vm_id']
1602 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s': %s",
1603 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
1607 for net
in instanceDict
['nets']:
1609 continue #skip not created nets
1613 myvim
.delete_network(net
['vim_net_id'])
1614 except vimconn
.vimconnNotFoundException
as e
:
1615 error_msg
+="\n NET id={} not found at VIM".format(net
['vim_net_id'])
1616 logger
.warn("NET '%s', VIM id '%s', from VNF_id '%s' not found",
1617 net
['uuid'], vm
['vim_net_id'], sce_vnf
['vnf_id'])
1618 except vimconn
.vimconnException
as e
:
1619 error_msg
+="\n Error: " + e
.http_code
+ " Net id=" + net
['vim_vm_id']
1620 logger
.error("Error %d deleting NET '%s', VIM id '%s', from VNF_id '%s': %s",
1621 e
.http_code
, net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'], str(e
))
1622 if len(error_msg
)>0:
1623 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
1625 return 'instance ' + message
+ ' deleted'
1627 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
1628 '''Refreshes a scenario instance. It modifies instanceDict'''
1630 - 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
1633 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
1634 #print "nfvo.refresh_instance begins"
1635 #print json.dumps(instanceDict, indent=4)
1637 #print "Getting the VIM URL and the VIM tenant_id"
1638 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
1640 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
1641 myvim
= vims
.values()[0]
1643 # 1. Getting VIM vm and net list
1644 vms_updated
= [] #List of VM instance uuids in openmano that were updated
1647 for sce_vnf
in instanceDict
['vnfs']:
1648 for vm
in sce_vnf
['vms']:
1649 vm_list
.append(vm
['vim_vm_id'])
1650 vms_notupdated
.append(vm
["uuid"])
1652 nets_updated
= [] #List of VM instance uuids in openmano that were updated
1655 for net
in instanceDict
['nets']:
1656 net_list
.append(net
['vim_net_id'])
1657 nets_notupdated
.append(net
["uuid"])
1660 # 1. Getting the status of all VMs
1661 vm_dict
= myvim
.refresh_vms_status(vm_list
)
1663 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
1664 for sce_vnf
in instanceDict
['vnfs']:
1665 for vm
in sce_vnf
['vms']:
1666 vm_id
= vm
['vim_vm_id']
1667 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
1668 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
1669 has_mgmt_iface
= False
1670 for iface
in vm
["interfaces"]:
1671 if iface
["type"]=="mgmt":
1672 has_mgmt_iface
= True
1673 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
1674 vm_dict
[vm_id
]['status'] = "ACTIVE"
1675 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'):
1676 vm
['status'] = vm_dict
[vm_id
]['status']
1677 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
1678 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
1679 # 2.1. Update in openmano DB the VMs whose status changed
1681 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
1682 vms_notupdated
.remove(vm
["uuid"])
1684 vms_updated
.append(vm
["uuid"])
1685 except db_base_Exception
as e
:
1686 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
1687 # 2.2. Update in openmano DB the interface VMs
1688 for interface
in interfaces
:
1689 #translate from vim_net_id to instance_net_id
1691 for net
in instanceDict
['nets']:
1692 if net
["vim_net_id"] == interface
["vim_net_id"]:
1693 network_id
= net
["uuid"]
1697 del interface
["vim_net_id"]
1699 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
1700 except db_base_Exception
as e
:
1701 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
1703 # 3. Getting the status of all nets
1704 net_dict
= myvim
.refresh_nets_status(net_list
)
1706 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
1707 # TODO: update nets inside a vnf
1708 for net
in instanceDict
['nets']:
1709 net_id
= net
['vim_net_id']
1710 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'):
1711 net
['status'] = net_dict
[net_id
]['status']
1712 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
1713 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
1714 # 5.1. Update in openmano DB the nets whose status changed
1716 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
1717 nets_notupdated
.remove(net
["uuid"])
1719 nets_updated
.append(net
["uuid"])
1720 except db_base_Exception
as e
:
1721 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
1722 except vimconn
.vimconnException
as e
:
1723 #logger.error("VIM exception %s %s", type(e).__name__, str(e))
1724 raise NfvoException(str(e
), e
.http_code
)
1726 # Returns appropriate output
1727 #print "nfvo.refresh_instance finishes"
1728 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
1729 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
1730 instance_id
= instanceDict
['uuid']
1731 if len(vms_notupdated
)+len(nets_notupdated
)>0:
1732 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
1733 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
1735 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
1737 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
1738 #print "Checking that the instance_id exists and getting the instance dictionary"
1739 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
1740 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
1742 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1743 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
1745 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
1746 myvim
= vims
.values()[0]
1749 input_vnfs
= action_dict
.pop("vnfs", [])
1750 input_vms
= action_dict
.pop("vms", [])
1751 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
1755 for sce_vnf
in instanceDict
['vnfs']:
1756 for vm
in sce_vnf
['vms']:
1757 if not action_over_all
:
1758 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
1759 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
1762 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
1763 if "console" in action_dict
:
1764 if data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
1765 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
1766 "description": "this console is only reachable by local interface",
1771 #print "console data", data
1773 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
1774 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
1775 "description": "%s//%s:%d/%s" %(data
["protocol"], console_thread
.host
, console_thread
.port
, data
["suffix"]),
1779 except NfvoException
as e
:
1780 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
1782 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
1784 except vimconn
.vimconnException
as e
:
1785 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
1788 if vm_ok
==0: #all goes wrong
1793 def create_or_use_console_proxy_thread(console_server
, console_port
):
1794 #look for a non-used port
1795 console_thread_key
= console_server
+ ":" + str(console_port
)
1796 if console_thread_key
in global_config
["console_thread"]:
1797 #global_config["console_thread"][console_thread_key].start_timeout()
1798 return global_config
["console_thread"][console_thread_key
]
1800 for port
in global_config
["console_port_iterator"]():
1801 print "create_or_use_console_proxy_thread() port:", port
1802 if port
in global_config
["console_ports"]:
1805 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
1807 global_config
["console_thread"][console_thread_key
] = clithread
1808 global_config
["console_ports"][port
] = console_thread_key
1810 except cli
.ConsoleProxyExceptionPortUsed
as e
:
1811 #port used, try with onoher
1813 except cli
.ConsoleProxyException
as e
:
1814 raise NfvoException(str(e
), HTTP_Bad_Request
)
1815 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
1817 def check_tenant(mydb
, tenant_id
):
1818 '''check that tenant exists at database'''
1819 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
1821 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
1824 def new_tenant(mydb
, tenant_dict
):
1825 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
1828 def delete_tenant(mydb
, tenant
):
1829 #get nfvo_tenant info
1831 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
1832 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
1833 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
1835 def new_datacenter(mydb
, datacenter_descriptor
):
1836 if "config" in datacenter_descriptor
:
1837 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
1838 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
1839 return datacenter_id
1841 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
1842 #obtain data, check that only one exist
1843 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
1845 datacenter_id
= datacenter
['uuid']
1846 where
={'uuid': datacenter
['uuid']}
1847 if "config" in datacenter_descriptor
:
1848 if datacenter_descriptor
['config']!=None:
1850 new_config_dict
= datacenter_descriptor
["config"]
1853 for k
in new_config_dict
:
1854 if new_config_dict
[k
]==None:
1857 config_dict
= yaml
.load(datacenter
["config"])
1858 config_dict
.update(new_config_dict
)
1862 except Exception as e
:
1863 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
1864 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
1865 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
1866 return datacenter_id
1868 def delete_datacenter(mydb
, datacenter
):
1869 #get nfvo_tenant info
1870 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
1871 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
1872 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
1874 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None):
1875 #get datacenter info
1876 if utils
.check_valid_uuid(datacenter
):
1877 vims
= get_vim(mydb
, datacenter_id
=datacenter
)
1879 vims
= get_vim(mydb
, datacenter_name
=datacenter
)
1881 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
1883 #print "nfvo.datacenter_action() error. Several datacenters found"
1884 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1886 datacenter_id
=vims
.keys()[0]
1887 myvim
=vims
[datacenter_id
]
1888 datacenter_name
=myvim
["name"]
1890 create_vim_tenant
=True if vim_tenant_id
==None and vim_tenant_name
==None else False
1892 #get nfvo_tenant info
1893 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
1894 if vim_tenant_name
==None:
1895 vim_tenant_name
=tenant_dict
['name']
1897 #check that this association does not exist before
1898 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
1899 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
1900 if len(tenants_datacenters
)>0:
1901 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
1903 vim_tenant_id_exist_atdb
=False
1904 if not create_vim_tenant
:
1905 where_
={"datacenter_id": datacenter_id
}
1906 if vim_tenant_id
!=None:
1907 where_
["vim_tenant_id"] = vim_tenant_id
1908 if vim_tenant_name
!=None:
1909 where_
["vim_tenant_name"] = vim_tenant_name
1910 #check if vim_tenant_id is already at database
1911 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
1912 if len(datacenter_tenants_dict
)>=1:
1913 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
1914 vim_tenant_id_exist_atdb
=True
1915 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
1917 datacenter_tenants_dict
= {}
1918 #insert at table datacenter_tenants
1919 else: #if vim_tenant_id==None:
1920 #create tenant at VIM if not provided
1922 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
1923 except vimconn
.vimconnException
as e
:
1924 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
1925 datacenter_tenants_dict
= {}
1926 datacenter_tenants_dict
["created"]="true"
1928 #fill datacenter_tenants table
1929 if not vim_tenant_id_exist_atdb
:
1930 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
1931 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
1932 datacenter_tenants_dict
["user"] = vim_username
1933 datacenter_tenants_dict
["passwd"] = vim_password
1934 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
1935 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
1936 datacenter_tenants_dict
["uuid"] = id_
1938 #fill tenants_datacenters table
1939 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
1940 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
1941 return datacenter_id
1943 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
1944 #get datacenter info
1945 if utils
.check_valid_uuid(datacenter
):
1946 vims
= get_vim(mydb
, datacenter_id
=datacenter
)
1948 vims
= get_vim(mydb
, datacenter_name
=datacenter
)
1950 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
1952 #print "nfvo.datacenter_action() error. Several datacenters found"
1953 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1954 datacenter_id
=vims
.keys()[0]
1955 myvim
=vims
[datacenter_id
]
1957 #get nfvo_tenant info
1958 if not tenant_id
or tenant_id
=="any":
1961 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
1962 tenant_uuid
= tenant_dict
['uuid']
1964 #check that this association exist before
1965 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
1967 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
1968 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
1969 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
1970 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
1972 #delete this association
1973 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
1975 #get vim_tenant info and deletes
1977 for tenant_datacenter_item
in tenant_datacenter_list
:
1978 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
1979 #try to delete vim:tenant
1981 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
1982 if vim_tenant_dict
['created']=='true':
1983 #delete tenant at VIM if created by NFVO
1985 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
1986 except vimconn
.vimconnException
as e
:
1987 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
1988 logger
.warn(warning
)
1989 except db_base_Exception
as e
:
1990 logger
.error("Cannot delete datacenter_tenants " + str(e
))
1991 pass #the error will be caused because dependencies, vim_tenant can not be deleted
1993 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
1995 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
1997 #get datacenter info
1998 if utils
.check_valid_uuid(datacenter
):
1999 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2001 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2003 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2005 #print "nfvo.datacenter_action() error. Several datacenters found"
2006 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2007 datacenter_id
=vims
.keys()[0]
2008 myvim
=vims
[datacenter_id
]
2010 if 'net-update' in action_dict
:
2012 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2014 except vimconn
.vimconnException
as e
:
2015 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2016 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2017 #update nets Change from VIM format to NFVO format
2020 net_nfvo
={'datacenter_id': datacenter_id
}
2021 net_nfvo
['name'] = net
['name']
2022 #net_nfvo['description']= net['name']
2023 net_nfvo
['vim_net_id'] = net
['id']
2024 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2025 net_nfvo
['shared'] = net
['shared']
2026 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2027 net_list
.append(net_nfvo
)
2028 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2029 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2031 elif 'net-edit' in action_dict
:
2032 net
= action_dict
['net-edit'].pop('net')
2033 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2034 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2035 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2037 elif 'net-delete' in action_dict
:
2038 net
= action_dict
['net-deelte'].get('net')
2039 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2040 result
= mydb
.delete_row(FROM
='datacenter_nets',
2041 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2045 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2047 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2048 #get datacenter info
2049 if utils
.check_valid_uuid(datacenter
):
2050 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2052 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2054 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2056 #print "nfvo.datacenter_action() error. Several datacenters found"
2057 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2058 datacenter_id
=vims
.keys()[0]
2060 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2061 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2062 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2065 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2066 #get datacenter info
2067 if utils
.check_valid_uuid(datacenter
):
2068 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2070 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2072 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2074 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2075 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2076 datacenter_id
=vims
.keys()[0]
2077 myvim
=vims
[datacenter_id
]
2080 action_dict
= action_dict
["netmap"]
2081 if 'vim_id' in action_dict
:
2082 filter_dict
["id"] = action_dict
['vim_id']
2083 if 'vim_name' in action_dict
:
2084 filter_dict
["name"] = action_dict
['vim_name']
2086 filter_dict
["shared"] = True
2089 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
2090 except vimconn
.vimconnException
as e
:
2091 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
2092 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2093 if len(vim_nets
)>1 and action_dict
:
2094 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
2095 elif len(vim_nets
)==0: # and action_dict:
2096 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
2098 for net
in vim_nets
:
2099 net_nfvo
={'datacenter_id': datacenter_id
}
2100 if action_dict
and "name" in action_dict
:
2101 net_nfvo
['name'] = action_dict
['name']
2103 net_nfvo
['name'] = net
['name']
2104 #net_nfvo['description']= net['name']
2105 net_nfvo
['vim_net_id'] = net
['id']
2106 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2107 net_nfvo
['shared'] = net
['shared']
2108 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2110 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2111 net_nfvo
["status"] = "OK"
2112 net_nfvo
["uuid"] = net_id
2113 except db_base_Exception
as e
:
2117 net_nfvo
["status"] = "FAIL: " + str(e
)
2118 net_list
.append(net_nfvo
)
2121 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2122 #get datacenter info
2123 if utils
.check_valid_uuid(datacenter
):
2124 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2126 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2128 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2130 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2131 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2132 datacenter_id
=vims
.keys()[0]
2133 myvim
=vims
[datacenter_id
]
2136 if utils
.check_valid_uuid(name
):
2137 filter_dict
["id"] = name
2139 filter_dict
["name"] = name
2141 if item
=="networks":
2142 #filter_dict['tenant_id'] = myvim['tenant_id']
2143 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2144 elif item
=="tenants":
2145 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2147 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2148 logger
.debug("vim_action response ", content
) #update nets Change from VIM format to NFVO format
2149 if name
and len(content
)==1:
2150 return {item
[:-1]: content
[0]}
2151 elif name
and len(content
)==0:
2152 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
2155 return {item
: content
}
2156 except vimconn
.vimconnException
as e
:
2157 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
2158 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
2160 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
2161 #get datacenter info
2162 if tenant_id
== "any":
2165 if utils
.check_valid_uuid(datacenter
):
2166 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2168 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2170 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2172 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2173 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2174 datacenter_id
=vims
.keys()[0]
2175 myvim
=vims
[datacenter_id
]
2177 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2178 logger
.debug("vim_action_delete vim response: " + str(content
))
2179 items
= content
.values()[0]
2180 if type(items
)==list and len(items
)==0:
2181 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
2182 elif type(items
)==list and len(items
)>1:
2183 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
2184 else: # it is a dict
2185 item_id
= items
["id"]
2186 item_name
= str(items
.get("name"))
2189 if item
=="networks":
2190 content
= myvim
.delete_network(item_id
)
2191 elif item
=="tenants":
2192 content
= myvim
.delete_tenant(item_id
)
2194 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2195 except vimconn
.vimconnException
as e
:
2196 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
2197 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
2199 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
2201 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2202 #get datacenter info
2203 print "vim_action_create descriptor", descriptor
2204 if tenant_id
== "any":
2207 if utils
.check_valid_uuid(datacenter
):
2208 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2210 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2212 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2214 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2215 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2216 datacenter_id
=vims
.keys()[0]
2217 myvim
=vims
[datacenter_id
]
2220 if item
=="networks":
2221 net
= descriptor
["network"]
2222 net_name
= net
.pop("name")
2223 net_type
= net
.pop("type", "bridge")
2224 net_public
=net
.pop("shared", False)
2225 content
= myvim
.new_network(net_name
, net_type
, net_public
, **net
)
2226 elif item
=="tenants":
2227 tenant
= descriptor
["tenant"]
2228 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2230 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2231 except vimconn
.vimconnException
as e
:
2232 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
2234 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)