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