1 # -*- coding: utf-8 -*-
4 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
5 # This file is part of openmano
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
25 NFVO engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances
27 __author__
="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
28 __date__
="$16-sep-2014 22:05:01$"
34 from db_base
import HTTP_Unauthorized
, HTTP_Bad_Request
, HTTP_Internal_Server_Error
, HTTP_Not_Found
,\
35 HTTP_Conflict
, HTTP_Method_Not_Allowed
36 import console_proxy_thread
as cli
40 from db_base
import db_base_Exception
43 global vimconn_imported
47 vimconn_imported
={} #dictionary with VIM type as key, loaded module as value
48 logger
= logging
.getLogger('openmano.nfvo')
50 class NfvoException(Exception):
51 def __init__(self
, message
, http_code
):
52 self
.http_code
= http_code
53 Exception.__init
__(self
, message
)
56 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
58 return result, content:
59 <0, error_text upon error
60 nb_records, flavor_list on success
63 WHERE_dict
['vnf_id'] = vnf_id
64 if nfvo_tenant
is not None:
65 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
67 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
68 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
69 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
70 #print "get_flavor_list result:", result
71 #print "get_flavor_list content:", content
73 for flavor
in flavors
:
74 flavorList
.append(flavor
['flavor_id'])
77 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
79 return result, content:
80 <0, error_text upon error
81 nb_records, flavor_list on success
84 WHERE_dict
['vnf_id'] = vnf_id
85 if nfvo_tenant
is not None:
86 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
88 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
89 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
92 imageList
.append(image
['image_id'])
95 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
96 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
97 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
98 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
99 raise exception upon error
102 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
103 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
104 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
105 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
106 if nfvo_tenant
or vim_tenant
:
107 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'
108 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
109 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
112 from_
= 'datacenters as d'
113 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
115 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
118 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
119 if vim
["config"] != None:
120 extra
.update(yaml
.load(vim
["config"]))
121 if vim
["type"] not in vimconn_imported
:
124 module
= "vimconn_" + vim
["type"]
125 module_info
= imp
.find_module(module
)
126 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
127 vimconn_imported
[vim
["type"]] = vim_conn
128 except (IOError, ImportError) as e
:
129 if module_info
and module_info
[0]:
130 file.close(module_info
[0])
131 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
132 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
136 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
137 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
138 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
139 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
), tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
140 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
141 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
144 except Exception as e
:
145 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
147 except db_base_Exception
as e
:
148 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
150 def rollback(mydb
, vims
, rollback_list
):
152 #delete things by reverse order
153 for i
in range(len(rollback_list
)-1, -1, -1):
154 item
= rollback_list
[i
]
155 if item
["where"]=="vim":
156 if item
["vim_id"] not in vims
:
158 vim
=vims
[ item
["vim_id"] ]
160 if item
["what"]=="image":
161 vim
.delete_image(item
["uuid"])
162 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
163 elif item
["what"]=="flavor":
164 vim
.delete_flavor(item
["uuid"])
165 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
166 elif item
["what"]=="network":
167 vim
.delete_network(item
["uuid"])
168 elif item
["what"]=="vm":
169 vim
.delete_vminstance(item
["uuid"])
170 except vimconn
.vimconnException
as e
:
171 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
172 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
173 except db_base_Exception
as e
:
174 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
178 if item
["what"]=="image":
179 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
180 elif item
["what"]=="flavor":
181 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
182 except db_base_Exception
as e
:
183 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
184 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
185 if len(undeleted_items
)==0:
186 return True," Rollback successful."
188 return False," Rollback fails to delete: " + str(undeleted_items
)
190 def check_vnf_descriptor(vnf_descriptor
):
192 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
194 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
196 #dataplane interfaces
197 for numa
in vnfc
.get("numas",() ):
198 for interface
in numa
.get("interfaces",()):
199 if interface
["name"] in name_list
:
200 raise NfvoException("Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC"\
201 .format(vnfc
["name"], interface
["name"]),
203 name_list
.append( interface
["name"] )
205 for interface
in vnfc
.get("bridge-ifaces",() ):
206 if interface
["name"] in name_list
:
207 raise NfvoException("Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC"\
208 .format(vnfc
["name"], interface
["name"]),
210 name_list
.append( interface
["name"] )
211 vnfc_interfaces
[ vnfc
["name"] ] = name_list
213 #check if the info in external_connections matches with the one in the vnfcs
215 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
216 if external_connection
["name"] in name_list
:
217 raise NfvoException("Error at vnf:external-connections:name, value '{}' already used as an external-connection"\
218 .format(external_connection
["name"]),
220 name_list
.append(external_connection
["name"])
221 if external_connection
["VNFC"] not in vnfc_interfaces
:
222 raise NfvoException("Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC"\
223 .format(external_connection
["name"], external_connection
["VNFC"]),
226 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
227 raise NfvoException("Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC"\
228 .format(external_connection
["name"], external_connection
["local_iface_name"]),
231 #check if the info in internal_connections matches with the one in the vnfcs
233 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
234 if internal_connection
["name"] in name_list
:
235 raise NfvoException("Error at vnf:internal-connections:name, value '%s' already used as an internal-connection"\
236 .format(internal_connection
["name"]),
238 name_list
.append(internal_connection
["name"])
239 #We should check that internal-connections of type "ptp" have only 2 elements
240 if len(internal_connection
["elements"])>2 and internal_connection
["type"] == "ptp":
241 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements, size must be 2 for a type:'ptp'"\
242 .format(internal_connection
["name"]),
244 for port
in internal_connection
["elements"]:
245 if port
["VNFC"] not in vnfc_interfaces
:
246 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC"\
247 .format(internal_connection
["name"], port
["VNFC"]),
249 if port
["local_iface_name"] not in vnfc_interfaces
[ port
["VNFC"] ]:
250 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC"\
251 .format(internal_connection
["name"], port
["local_iface_name"]),
253 return -HTTP_Bad_Request
,
255 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
257 if only_create_at_vim
:
258 image_mano_id
= image_dict
['uuid']
260 if image_dict
['location'] is not None:
261 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
263 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
265 image_mano_id
= images
[0]['uuid']
268 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
269 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
270 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
272 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
273 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
274 #create image at every vim
275 for vim_id
,vim
in vims
.iteritems():
276 image_created
="false"
278 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
279 #look at VIM if this image exist
281 if image_dict
['location'] is not None:
282 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
285 filter_dict
['name']=image_dict
['universal_name']
286 filter_dict
['checksum']=image_dict
['checksum']
287 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
288 vim_images
= vim
.get_image_list(filter_dict
)
289 if len(vim_images
) > 1:
290 raise NfvoException("More than one candidate VIM image found for filter: " + str(filter_dict
), HTTP_Conflict
)
291 elif len(vim_images
) == 0:
292 raise NfvoException("Image not found at VIM with filter: '%s'", str(filter_dict
))
294 image_vim_id
= vim_images
[0].id
296 except vimconn
.vimconnNotFoundException
as e
:
297 #Create the image in VIM
299 image_vim_id
= vim
.new_image(image_dict
)
300 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
302 except vimconn
.vimconnException
as e
:
304 logger
.error("Error creating image at VIM: %s", str(e
))
306 image_vim_id
= str(e
)
307 logger
.warn("Error creating image at VIM: %s", str(e
))
309 except vimconn
.vimconnException
as e
:
310 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
311 image_vim_id
= str(e
)
313 #if we reach here, the image has been created or existed
315 #add new vim_id at datacenters_images
316 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
317 elif image_db
[0]["vim_id"]!=image_vim_id
:
318 #modify existing vim_id at datacenters_images
319 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
321 return image_vim_id
if only_create_at_vim
else image_mano_id
323 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
324 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
325 'ram':flavor_dict
.get('ram'),
326 'vcpus':flavor_dict
.get('vcpus'),
328 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
329 del flavor_dict
['extended']
330 if 'extended' in flavor_dict
:
331 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
333 #look if flavor exist
334 if only_create_at_vim
:
335 flavor_mano_id
= flavor_dict
['uuid']
337 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
339 flavor_mano_id
= flavors
[0]['uuid']
342 #create one by one the images of aditional disks
343 dev_image_list
=[] #list of images
344 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
346 for device
in flavor_dict
['extended'].get('devices',[]):
347 if "image" not in device
or "image name" not in device
:
350 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
351 image_dict
['universal_name']=device
.get('image name')
352 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
353 image_dict
['location']=device
.get('image')
354 image_dict
['checksum']=device
.get('image checksum')
355 image_metadata_dict
= device
.get('image metadata', None)
356 image_metadata_str
= None
357 if image_metadata_dict
!= None:
358 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
359 image_dict
['metadata']=image_metadata_str
360 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
361 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
362 dev_image_list
.append(image_id
)
364 temp_flavor_dict
['name'] = flavor_dict
['name']
365 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
366 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
367 flavor_mano_id
= content
368 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
369 #create flavor at every vim
370 if 'uuid' in flavor_dict
:
371 del flavor_dict
['uuid']
373 for vim_id
,vim
in vims
.items():
374 flavor_created
="false"
376 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
377 #look at VIM if this flavor exist SKIPPED
378 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
380 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
384 #Create the flavor in VIM
385 #Translate images at devices from MANO id to VIM id
386 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
387 #make a copy of original devices
389 for device
in flavor_dict
["extended"].get("devices",[]):
392 devices_original
.append(dev
)
393 if 'image' in device
:
395 if 'image metadata' in device
:
396 del device
['image metadata']
398 for index
in range(0,len(devices_original
)) :
399 device
=devices_original
[index
]
400 if "image" not in device
or "image name" not in device
:
403 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
404 image_dict
['universal_name']=device
.get('image name')
405 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
406 image_dict
['location']=device
.get('image')
407 image_dict
['checksum']=device
.get('image checksum')
408 image_metadata_dict
= device
.get('image metadata', None)
409 image_metadata_str
= None
410 if image_metadata_dict
!= None:
411 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
412 image_dict
['metadata']=image_metadata_str
413 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
414 image_dict
["uuid"]=image_mano_id
415 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
416 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
419 #check that this vim_id exist in VIM, if not create
420 flavor_vim_id
=flavor_db
[0]["vim_id"]
422 vim
.get_flavor(flavor_vim_id
)
423 continue #flavor exist
424 except vimconn
.vimconnException
:
426 #create flavor at vim
427 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
429 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
430 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
431 flavor_created
="true"
432 except vimconn
.vimconnException
as e
:
434 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
436 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
438 #if reach here the flavor has been create or exist
439 if len(flavor_db
)==0:
440 #add new vim_id at datacenters_flavors
441 mydb
.new_row('datacenters_flavors', {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
, 'created':flavor_created
})
442 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
443 #modify existing vim_id at datacenters_flavors
444 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
446 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
448 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
451 # Step 1. Check the VNF descriptor
452 check_vnf_descriptor(vnf_descriptor
)
453 # Step 2. Check tenant exist
454 if tenant_id
!= "any":
455 check_tenant(mydb
, tenant_id
)
456 if "tenant_id" in vnf_descriptor
["vnf"]:
457 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
458 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
461 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
462 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
463 vims
= get_vim(mydb
, tenant_id
)
467 # Step 4. Review the descriptor and add missing fields
468 #print vnf_descriptor
469 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
470 vnf_name
= vnf_descriptor
['vnf']['name']
471 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
472 if "physical" in vnf_descriptor
['vnf']:
473 del vnf_descriptor
['vnf']['physical']
474 #print vnf_descriptor
475 # Step 5. Check internal connections
476 # TODO: to be moved to step 1????
477 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
478 for ic
in internal_connections
:
479 if len(ic
['elements'])>2 and ic
['type']=='ptp':
480 raise NfvoException("Mismatch 'type':'ptp' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'data'".format(len(ic
), ic
['name']),
482 elif len(ic
['elements'])==2 and ic
['type']=='data':
483 raise NfvoException("Mismatch 'type':'data' with 2 elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'ptp'".format(ic
['name']),
486 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
487 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
488 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
490 #For each VNFC, we add it to the VNFCDict and we create a flavor.
491 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
492 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
494 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
495 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
497 VNFCitem
["name"] = vnfc
['name']
498 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
500 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
503 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
504 myflavorDict
["description"] = VNFCitem
["description"]
505 myflavorDict
["ram"] = vnfc
.get("ram", 0)
506 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
507 myflavorDict
["disk"] = vnfc
.get("disk", 1)
508 myflavorDict
["extended"] = {}
510 devices
= vnfc
.get("devices")
512 myflavorDict
["extended"]["devices"] = devices
515 # 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
516 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
518 # Previous code has been commented
519 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
520 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
521 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
522 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
524 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
526 # print "Error creating flavor: unknown processor model. Rollback successful."
527 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
529 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
530 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
532 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
533 myflavorDict
['extended']['numas'] = vnfc
['numas']
537 # Step 6.2 New flavors are created in the VIM
538 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
540 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
541 VNFCitem
["flavor_id"] = flavor_id
542 VNFCDict
[vnfc
['name']] = VNFCitem
544 logger
.debug("Creating new images in the VIM for each VNFC")
545 # Step 6.3 New images are created in the VIM
546 #For each VNFC, we must create the appropriate image.
547 #This "for" loop might be integrated with the previous one
548 #In case this integration is made, the VNFCDict might become a VNFClist.
549 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
550 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
552 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
553 image_dict
['universal_name']=vnfc
.get('image name')
554 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
555 image_dict
['location']=vnfc
.get('VNFC image')
556 image_dict
['checksum']=vnfc
.get('image checksum')
557 image_metadata_dict
= vnfc
.get('image metadata', None)
558 image_metadata_str
= None
559 if image_metadata_dict
is not None:
560 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
561 image_dict
['metadata']=image_metadata_str
562 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
563 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
564 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
565 VNFCDict
[vnfc
['name']]["image_id"] = image_id
566 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
569 # Step 7. Storing the VNF descriptor in the repository
570 if "descriptor" not in vnf_descriptor
["vnf"]:
571 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
573 # Step 8. Adding the VNF to the NFVO DB
574 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
576 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
577 _
, message
= rollback(mydb
, vims
, rollback_list
)
578 if isinstance(e
, db_base_Exception
):
579 error_text
= "Exception at database"
580 elif isinstance(e
, KeyError):
581 error_text
= "KeyError exception "
582 e
.http_code
= HTTP_Internal_Server_Error
584 error_text
= "Exception at VIM"
585 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
586 #logger.error("start_scenario %s", error_text)
587 raise NfvoException(error_text
, e
.http_code
)
589 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
592 # Step 1. Check the VNF descriptor
593 check_vnf_descriptor(vnf_descriptor
)
594 # Step 2. Check tenant exist
595 if tenant_id
!= "any":
596 check_tenant(mydb
, tenant_id
)
597 if "tenant_id" in vnf_descriptor
["vnf"]:
598 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
599 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
602 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
603 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
604 vims
= get_vim(mydb
, tenant_id
)
608 # Step 4. Review the descriptor and add missing fields
609 #print vnf_descriptor
610 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
611 vnf_name
= vnf_descriptor
['vnf']['name']
612 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
613 if "physical" in vnf_descriptor
['vnf']:
614 del vnf_descriptor
['vnf']['physical']
615 #print vnf_descriptor
616 # Step 5. Check internal connections
617 # TODO: to be moved to step 1????
618 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
619 for ic
in internal_connections
:
620 if len(ic
['elements'])>2 and ic
['type']=='e-line':
621 raise NfvoException("Mismatch 'type':'e-line' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'e-lan'".format(len(ic
), ic
['name']),
624 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
625 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
626 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
628 #For each VNFC, we add it to the VNFCDict and we create a flavor.
629 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
630 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
632 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
633 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
635 VNFCitem
["name"] = vnfc
['name']
636 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
638 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
641 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
642 myflavorDict
["description"] = VNFCitem
["description"]
643 myflavorDict
["ram"] = vnfc
.get("ram", 0)
644 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
645 myflavorDict
["disk"] = vnfc
.get("disk", 1)
646 myflavorDict
["extended"] = {}
648 devices
= vnfc
.get("devices")
650 myflavorDict
["extended"]["devices"] = devices
653 # 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
654 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
656 # Previous code has been commented
657 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
658 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
659 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
660 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
662 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
664 # print "Error creating flavor: unknown processor model. Rollback successful."
665 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
667 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
668 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
670 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
671 myflavorDict
['extended']['numas'] = vnfc
['numas']
675 # Step 6.2 New flavors are created in the VIM
676 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
678 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
679 VNFCitem
["flavor_id"] = flavor_id
680 VNFCDict
[vnfc
['name']] = VNFCitem
682 logger
.debug("Creating new images in the VIM for each VNFC")
683 # Step 6.3 New images are created in the VIM
684 #For each VNFC, we must create the appropriate image.
685 #This "for" loop might be integrated with the previous one
686 #In case this integration is made, the VNFCDict might become a VNFClist.
687 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
688 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
690 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
691 image_dict
['universal_name']=vnfc
.get('image name')
692 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
693 image_dict
['location']=vnfc
.get('VNFC image')
694 image_dict
['checksum']=vnfc
.get('image checksum')
695 image_metadata_dict
= vnfc
.get('image metadata', None)
696 image_metadata_str
= None
697 if image_metadata_dict
is not None:
698 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
699 image_dict
['metadata']=image_metadata_str
700 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
701 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
702 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
703 VNFCDict
[vnfc
['name']]["image_id"] = image_id
704 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
707 # Step 7. Storing the VNF descriptor in the repository
708 if "descriptor" not in vnf_descriptor
["vnf"]:
709 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
711 # Step 8. Adding the VNF to the NFVO DB
712 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
714 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
715 _
, message
= rollback(mydb
, vims
, rollback_list
)
716 if isinstance(e
, db_base_Exception
):
717 error_text
= "Exception at database"
718 elif isinstance(e
, KeyError):
719 error_text
= "KeyError exception "
720 e
.http_code
= HTTP_Internal_Server_Error
722 error_text
= "Exception at VIM"
723 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
724 #logger.error("start_scenario %s", error_text)
725 raise NfvoException(error_text
, e
.http_code
)
727 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
728 #check valid tenant_id
729 check_tenant(mydb
, tenant_id
)
732 if tenant_id
!= "any":
733 where_or
["tenant_id"] = tenant_id
734 where_or
["public"] = True
735 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
738 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
739 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
740 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
741 data
={'vnf' : filtered_content
}
743 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
744 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description'),
745 WHERE
={'vnfs.uuid': vnf_id
} )
747 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
749 data
['vnf']['VNFC'] = content
750 #TODO: GET all the information from a VNFC and include it in the output.
753 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
754 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
755 WHERE
={'vnfs.uuid': vnf_id
} )
756 data
['vnf']['nets'] = content
758 #GET ip-profile for each net
759 for net
in data
['vnf']['nets']:
760 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
761 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
762 WHERE
={'net_id': net
["uuid"]} )
763 if len(ipprofiles
)==1:
764 net
["ip_profile"] = ipprofiles
[0]
765 elif len(ipprofiles
)>1:
766 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
769 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
771 #GET External Interfaces
772 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
773 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
774 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
775 WHERE
={'vnfs.uuid': vnf_id
},
776 WHERE_NOT
={'interfaces.external_name': None} )
778 data
['vnf']['external-connections'] = content
783 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
785 if tenant_id
!= "any":
786 check_tenant(mydb
, tenant_id
)
787 # Get the URL of the VIM from the nfvo_tenant and the datacenter
788 vims
= get_vim(mydb
, tenant_id
)
792 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
794 if tenant_id
!= "any":
795 where_or
["tenant_id"] = tenant_id
796 where_or
["public"] = True
797 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
800 # "Getting the list of flavors and tenants of the VNF"
801 flavorList
= get_flavorlist(mydb
, vnf_id
)
802 if len(flavorList
)==0:
803 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
805 imageList
= get_imagelist(mydb
, vnf_id
)
806 if len(imageList
)==0:
807 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
809 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
811 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
814 for flavor
in flavorList
:
815 #check if flavor is used by other vnf
817 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
819 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
821 #flavor not used, must be deleted
823 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
825 if flavor_vim
["datacenter_id"] not in vims
:
827 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
829 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
831 myvim
.delete_flavor(flavor_vim
["vim_id"])
832 except vimconn
.vimconnNotFoundException
as e
:
833 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
834 except vimconn
.vimconnException
as e
:
835 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
836 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
837 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
838 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
839 mydb
.delete_row_by_id('flavors', flavor
)
840 except db_base_Exception
as e
:
841 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
842 undeletedItems
.append("flavor %s" % flavor
)
845 for image
in imageList
:
847 #check if image is used by other vnf
848 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
850 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
852 #image not used, must be deleted
854 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
856 if image_vim
["datacenter_id"] not in vims
:
858 if image_vim
['created']=='false': #skip this image because not created by openmano
860 myvim
=vims
[ image_vim
["datacenter_id"] ]
862 myvim
.delete_image(image_vim
["vim_id"])
863 except vimconn
.vimconnNotFoundException
as e
:
864 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
865 except vimconn
.vimconnException
as e
:
866 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
867 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
868 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
869 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
870 mydb
.delete_row_by_id('images', image
)
871 except db_base_Exception
as e
:
872 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
873 undeletedItems
.append("image %s" % image
)
875 return vnf_id
+ " " + vnf
["name"]
877 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
879 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
880 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
884 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
885 myvim
= vims
.values()[0]
886 result
,servers
= myvim
.get_hosts_info()
888 return result
, servers
889 topology
= {'name':myvim
['name'] , 'servers': servers
}
890 return result
, topology
892 def get_hosts(mydb
, nfvo_tenant_id
):
893 vims
= get_vim(mydb
, nfvo_tenant_id
)
895 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
897 #print "nfvo.datacenter_action() error. Several datacenters found"
898 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
899 myvim
= vims
.values()[0]
901 hosts
= myvim
.get_hosts()
902 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
904 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
906 server
={'name':host
['name'], 'vms':[]}
907 for vm
in host
['instances']:
908 #get internal name and model
910 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
911 WHERE
={'vim_vm_id':vm
['id']} )
913 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
915 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
917 except db_base_Exception
as e
:
918 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
919 datacenter
['Datacenters'][0]['servers'].append(server
)
920 #return -400, "en construccion"
922 #print 'datacenters '+ json.dumps(datacenter, indent=4)
924 except vimconn
.vimconnException
as e
:
925 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
927 def new_scenario(mydb
, tenant_id
, topo
):
929 # result, vims = get_vim(mydb, tenant_id)
931 # return result, vims
933 if tenant_id
!= "any":
934 check_tenant(mydb
, tenant_id
)
935 if "tenant_id" in topo
:
936 if topo
["tenant_id"] != tenant_id
:
937 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
942 #1.1: get VNFs and external_networks (other_nets).
944 other_nets
={} #external_networks, bridge_networks and data_networkds
945 nodes
= topo
['topology']['nodes']
946 for k
in nodes
.keys():
947 if nodes
[k
]['type'] == 'VNF':
949 vnfs
[k
]['ifaces'] = {}
950 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
951 other_nets
[k
] = nodes
[k
]
952 other_nets
[k
]['external']=True
953 elif nodes
[k
]['type'] == 'network':
954 other_nets
[k
] = nodes
[k
]
955 other_nets
[k
]['external']=False
958 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
959 for name
,vnf
in vnfs
.items():
961 where_or
={"tenant_id": tenant_id
, 'public': "true"}
963 error_pos
= "'topology':'nodes':'" + name
+ "'"
965 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
966 where
['uuid'] = vnf
['vnf_id']
967 if 'VNF model' in vnf
:
968 error_text
+= " 'VNF model' " + vnf
['VNF model']
969 where
['name'] = vnf
['VNF model']
971 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
973 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
979 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
981 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
982 vnf
['uuid']=vnf_db
[0]['uuid']
983 vnf
['description']=vnf_db
[0]['description']
984 #get external interfaces
985 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
986 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
987 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
988 for ext_iface
in ext_ifaces
:
989 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
991 #1.4 get list of connections
992 conections
= topo
['topology']['connections']
994 conections_list_name
= []
995 for k
in conections
.keys():
996 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
997 ifaces_list
= conections
[k
]['nodes'].items()
998 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1000 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1001 for k2
in conection_pair_list
:
1004 con_type
= conections
[k
].get("type", "link")
1005 if con_type
!= "link":
1007 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1008 other_nets
[k
] = {'external': False}
1009 if conections
[k
].get("graph"):
1010 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1011 ifaces_list
.append( (k
, None) )
1014 if con_type
== "external_network":
1015 other_nets
[k
]['external'] = True
1016 if conections
[k
].get("model"):
1017 other_nets
[k
]["model"] = conections
[k
]["model"]
1019 other_nets
[k
]["model"] = k
1020 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1021 other_nets
[k
]["model"] = con_type
1023 conections_list_name
.append(k
)
1024 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)
1025 #print set(ifaces_list)
1026 #check valid VNF and iface names
1027 for iface
in ifaces_list
:
1028 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1029 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1030 str(k
), iface
[0]), HTTP_Not_Found
)
1031 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1032 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1033 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1035 #1.5 unify connections from the pair list to a consolidated list
1037 while index
< len(conections_list
):
1039 while index2
< len(conections_list
):
1040 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1041 conections_list
[index
] |
= conections_list
[index2
]
1042 del conections_list
[index2
]
1043 del conections_list_name
[index2
]
1046 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1048 #for k in conections_list:
1053 #1.6 Delete non external nets
1054 # for k in other_nets.keys():
1055 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1056 # for con in conections_list:
1058 # for index in range(0,len(con)):
1059 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1060 # for index in delete_indexes:
1063 #1.7: Check external_ports are present at database table datacenter_nets
1064 for k
,net
in other_nets
.items():
1065 error_pos
= "'topology':'nodes':'" + k
+ "'"
1066 if net
['external']==False:
1067 if 'name' not in net
:
1069 if 'model' not in net
:
1070 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1071 if net
['model']=='bridge_net':
1072 net
['type']='bridge';
1073 elif net
['model']=='dataplane_net':
1076 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1078 #IF we do not want to check that external network exist at datacenter
1083 # if 'net_id' in net:
1084 # error_text += " 'net_id' " + net['net_id']
1085 # WHERE_['uuid'] = net['net_id']
1086 # if 'model' in net:
1087 # error_text += " 'model' " + net['model']
1088 # WHERE_['name'] = net['model']
1089 # if len(WHERE_) == 0:
1090 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1091 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1092 # FROM='datacenter_nets', WHERE=WHERE_ )
1094 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1096 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1097 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1099 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1100 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1101 # other_nets[k].update(net_db[0])
1104 net_nb
=0 #Number of nets
1105 for con
in conections_list
:
1106 #check if this is connected to a external net
1110 for index
in range(0,len(con
)):
1111 #check if this is connected to a external net
1112 for net_key
in other_nets
.keys():
1113 if con
[index
][0]==net_key
:
1114 if other_net_index
>=0:
1115 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1116 #print "nfvo.new_scenario " + error_text
1117 raise NfvoException(error_text
, HTTP_Bad_Request
)
1119 other_net_index
= index
1120 net_target
= net_key
1122 #print "other_net_index", other_net_index
1124 if other_net_index
>=0:
1125 del con
[other_net_index
]
1126 #IF we do not want to check that external network exist at datacenter
1127 if other_nets
[net_target
]['external'] :
1128 if "name" not in other_nets
[net_target
]:
1129 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1130 if other_nets
[net_target
]["type"] == "external_network":
1131 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1132 other_nets
[net_target
]["type"] = "data"
1134 other_nets
[net_target
]["type"] = "bridge"
1136 # if other_nets[net_target]['external'] :
1137 # 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
1138 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1139 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1140 # print "nfvo.new_scenario " + error_text
1141 # return -HTTP_Bad_Request, error_text
1144 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1147 net_type_bridge
=False
1149 net_target
= "__-__net"+str(net_nb
)
1150 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1151 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1154 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1155 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1156 if iface_type
=='mgmt' or iface_type
=='bridge':
1157 net_type_bridge
= True
1159 net_type_data
= True
1160 if net_type_bridge
and net_type_data
:
1161 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1162 #print "nfvo.new_scenario " + error_text
1163 raise NfvoException(error_text
, HTTP_Bad_Request
)
1164 elif net_type_bridge
:
1167 type_
='data' if len(con
)>2 else 'ptp'
1168 net_list
[net_target
]['type'] = type_
1171 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1172 #print "nfvo.new_scenario " + error_text
1174 raise NfvoException(error_text
, HTTP_Bad_Request
)
1176 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1177 #1.8.1 obtain management net
1178 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1179 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1180 #1.8.2 check all interfaces from all vnfs
1182 add_mgmt_net
= False
1183 for vnf
in vnfs
.values():
1184 for iface
in vnf
['ifaces'].values():
1185 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1186 #iface not connected
1187 iface
['net_key'] = 'mgmt'
1189 if add_mgmt_net
and 'mgmt' not in net_list
:
1190 net_list
['mgmt']=mgmt_net
[0]
1191 net_list
['mgmt']['external']=True
1192 net_list
['mgmt']['graph']={'visible':False}
1194 net_list
.update(other_nets
)
1196 #print 'net_list', net_list
1201 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1202 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1203 'tenant_id':tenant_id
, 'name':topo
['name'],
1204 'description':topo
.get('description',topo
['name']),
1205 'public': topo
.get('public', False)
1210 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
):
1211 scenario
= scenario_dict
["scenario"]
1212 if tenant_id
!= "any":
1213 check_tenant(mydb
, tenant_id
)
1214 if "tenant_id" in scenario
:
1215 if scenario
["tenant_id"] != tenant_id
:
1216 print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1217 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1218 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1222 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1223 for name
,vnf
in scenario
["vnfs"].iteritems():
1225 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1227 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1229 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1230 where
['uuid'] = vnf
['vnf_id']
1231 if 'vnf_name' in vnf
:
1232 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1233 where
['name'] = vnf
['vnf_name']
1235 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1236 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1242 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1244 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1245 vnf
['uuid']=vnf_db
[0]['uuid']
1246 vnf
['description']=vnf_db
[0]['description']
1248 #get external interfaces
1249 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1250 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1251 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1252 for ext_iface
in ext_ifaces
:
1253 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1255 #2: Insert net_key at every vnf interface
1256 for net_name
,net
in scenario
["networks"].iteritems():
1257 net_type_bridge
=False
1259 for iface_dict
in net
["interfaces"]:
1260 for vnf
,iface
in iface_dict
.iteritems():
1261 if vnf
not in scenario
["vnfs"]:
1262 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1263 #print "nfvo.new_scenario_v02 " + error_text
1264 raise NfvoException(error_text
, HTTP_Not_Found
)
1265 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1266 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1267 #print "nfvo.new_scenario_v02 " + error_text
1268 raise NfvoException(error_text
, HTTP_Bad_Request
)
1269 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1270 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1271 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1272 #print "nfvo.new_scenario_v02 " + error_text
1273 raise NfvoException(error_text
, HTTP_Bad_Request
)
1274 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1275 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1276 if iface_type
=='mgmt' or iface_type
=='bridge':
1277 net_type_bridge
= True
1279 net_type_data
= True
1280 if net_type_bridge
and net_type_data
:
1281 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1282 #print "nfvo.new_scenario " + error_text
1283 raise NfvoException(error_text
, HTTP_Bad_Request
)
1284 elif net_type_bridge
:
1287 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1289 net
['name'] = net_name
1290 net
['external'] = net
.get('external', False)
1292 #3: insert at database
1293 scenario
["nets"] = scenario
["networks"]
1294 scenario
['tenant_id'] = tenant_id
1295 scenario_id
= mydb
.new_scenario( scenario
)
1298 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1299 data
["uuid"] = scenario_id
1300 data
["tenant_id"] = tenant_id
1301 c
= mydb
.edit_scenario( data
)
1304 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1305 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1306 datacenter_id
= None
1307 datacenter_name
=None
1308 if datacenter
!= None:
1309 if utils
.check_valid_uuid(datacenter
):
1310 datacenter_id
= datacenter
1312 datacenter_name
= datacenter
1313 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
)
1315 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
1317 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
1318 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1319 myvim
= vims
.values()[0]
1320 myvim_tenant
= myvim
['tenant_id']
1321 datacenter_id
= myvim
['id']
1322 datacenter_name
= myvim
['name']
1323 datacenter_tenant_id
= myvim
['config']['datacenter_tenant_id']
1326 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1327 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1328 scenarioDict
['datacenter_tenant_id'] = datacenter_tenant_id
1329 scenarioDict
['datacenter_id'] = datacenter_id
1330 #print '================scenarioDict======================='
1331 #print json.dumps(scenarioDict, indent=4)
1332 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1334 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1335 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1337 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1338 auxNetDict
['scenario'] = {}
1340 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1341 for sce_net
in scenarioDict
['nets']:
1342 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1344 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1345 myNetName
= myNetName
[0:255] #limit length
1346 myNetType
= sce_net
['type']
1348 myNetDict
["name"] = myNetName
1349 myNetDict
["type"] = myNetType
1350 myNetDict
["tenant_id"] = myvim_tenant
1351 myNetIPProfile
= sce_net
.get('ip_profile', None)
1353 #We should use the dictionary as input parameter for new_network
1355 if not sce_net
["external"]:
1356 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1357 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1358 sce_net
['vim_id'] = network_id
1359 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1360 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1361 sce_net
["created"] = True
1363 if sce_net
['vim_id'] == None:
1364 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1365 _
, message
= rollback(mydb
, vims
, rollbackList
)
1366 logger
.error("nfvo.start_scenario: %s", error_text
)
1367 raise NfvoException(error_text
, HTTP_Bad_Request
)
1368 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1369 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1371 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1372 #For each vnf net, we create it and we add it to instanceNetlist.
1373 for sce_vnf
in scenarioDict
['vnfs']:
1374 for net
in sce_vnf
['nets']:
1375 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1377 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1378 myNetName
= myNetName
[0:255] #limit length
1379 myNetType
= net
['type']
1381 myNetDict
["name"] = myNetName
1382 myNetDict
["type"] = myNetType
1383 myNetDict
["tenant_id"] = myvim_tenant
1384 myNetIPProfile
= net
.get('ip_profile', None)
1387 #We should use the dictionary as input parameter for new_network
1388 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1389 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1390 net
['vim_id'] = network_id
1391 if sce_vnf
['uuid'] not in auxNetDict
:
1392 auxNetDict
[sce_vnf
['uuid']] = {}
1393 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1394 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1395 net
["created"] = True
1397 #print "auxNetDict:"
1398 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1400 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1401 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1403 for sce_vnf
in scenarioDict
['vnfs']:
1404 for vm
in sce_vnf
['vms']:
1407 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1408 myVMDict
['name'] = "%s.%s.%d" % (instance_scenario_name
,sce_vnf
['name'],i
)
1409 #myVMDict['description'] = vm['description']
1410 myVMDict
['description'] = myVMDict
['name'][0:99]
1412 myVMDict
['start'] = "no"
1413 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1414 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1416 #create image at vim in case it not exist
1417 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1418 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1419 vm
['vim_image_id'] = image_id
1421 #create flavor at vim in case it not exist
1422 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1423 if flavor_dict
['extended']!=None:
1424 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1425 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1426 vm
['vim_flavor_id'] = flavor_id
1429 myVMDict
['imageRef'] = vm
['vim_image_id']
1430 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1431 myVMDict
['networks'] = []
1432 for iface
in vm
['interfaces']:
1434 if iface
['type']=="data":
1435 netDict
['type'] = iface
['model']
1436 elif "model" in iface
and iface
["model"]!=None:
1437 netDict
['model']=iface
['model']
1438 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1439 #discover type of interface looking at flavor
1440 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1441 for flavor_iface
in numa
.get('interfaces',[]):
1442 if flavor_iface
.get('name') == iface
['internal_name']:
1443 if flavor_iface
['dedicated'] == 'yes':
1444 netDict
['type']="PF" #passthrough
1445 elif flavor_iface
['dedicated'] == 'no':
1446 netDict
['type']="VF" #siov
1447 elif flavor_iface
['dedicated'] == 'yes:sriov':
1448 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1449 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1451 netDict
["use"]=iface
['type']
1452 if netDict
["use"]=="data" and not netDict
.get("type"):
1453 #print "netDict", netDict
1454 #print "iface", iface
1455 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'])
1456 if flavor_dict
.get('extended')==None:
1457 raise NfvoException(e_text
+ "After database migration some information is not available. \
1458 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1460 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1461 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1462 netDict
["type"]="virtual"
1463 if "vpci" in iface
and iface
["vpci"] is not None:
1464 netDict
['vpci'] = iface
['vpci']
1465 if "mac" in iface
and iface
["mac"] is not None:
1466 netDict
['mac_address'] = iface
['mac']
1467 netDict
['name'] = iface
['internal_name']
1468 if iface
['net_id'] is None:
1469 for vnf_iface
in sce_vnf
["interfaces"]:
1472 if vnf_iface
['interface_id']==iface
['uuid']:
1473 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1476 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1477 #skip bridge ifaces not connected to any net
1478 #if 'net_id' not in netDict or netDict['net_id']==None:
1480 myVMDict
['networks'].append(netDict
)
1481 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1482 #print myVMDict['name']
1483 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1484 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1485 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1486 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1487 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1488 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1489 vm
['vim_id'] = vm_id
1490 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1491 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1492 for net
in myVMDict
['networks']:
1494 for iface
in vm
['interfaces']:
1495 if net
["name"]==iface
["internal_name"]:
1496 iface
["vim_id"]=net
["vim_id"]
1499 logger
.debug("start scenario Deployment done")
1500 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1501 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1502 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1503 return mydb
.get_instance_scenario(instance_id
)
1505 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1506 _
, message
= rollback(mydb
, vims
, rollbackList
)
1507 if isinstance(e
, db_base_Exception
):
1508 error_text
= "Exception at database"
1510 error_text
= "Exception at VIM"
1511 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1512 #logger.error("start_scenario %s", error_text)
1513 raise NfvoException(error_text
, e
.http_code
)
1515 def unify_cloud_config(cloud_config
):
1516 index_to_delete
= []
1517 users
= cloud_config
.get("users", [])
1518 for index0
in range(0,len(users
)):
1519 if index0
in index_to_delete
:
1521 for index1
in range(index0
+1,len(users
)):
1522 if index1
in index_to_delete
:
1524 if users
[index0
]["name"] == users
[index1
]["name"]:
1525 index_to_delete
.append(index1
)
1526 for key
in users
[index1
].get("key-pairs",()):
1527 if "key-pairs" not in users
[index0
]:
1528 users
[index0
]["key-pairs"] = [key
]
1529 elif key
not in users
[index0
]["key-pairs"]:
1530 users
[index0
]["key-pairs"].append(key
)
1531 index_to_delete
.sort(reverse
=True)
1532 for index
in index_to_delete
:
1535 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None):
1536 datacenter_id
= None
1537 datacenter_name
= None
1538 if datacenter_id_name
:
1539 if utils
.check_valid_uuid(datacenter_id_name
):
1540 datacenter_id
= datacenter_id_name
1542 datacenter_name
= datacenter_id_name
1543 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
=None)
1545 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1547 #print "nfvo.datacenter_action() error. Several datacenters found"
1548 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1549 return vims
.keys()[0], vims
.values()[0]
1551 def new_scenario_v03(mydb
, tenant_id
, scenario_dict
):
1552 scenario
= scenario_dict
["scenario"]
1553 if tenant_id
!= "any":
1554 check_tenant(mydb
, tenant_id
)
1555 if "tenant_id" in scenario
:
1556 if scenario
["tenant_id"] != tenant_id
:
1557 logger("Tenant '%s' not found", tenant_id
)
1558 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1559 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1563 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1564 for name
,vnf
in scenario
["vnfs"].iteritems():
1566 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1568 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1570 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1571 where
['uuid'] = vnf
['vnf_id']
1572 if 'vnf_name' in vnf
:
1573 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1574 where
['name'] = vnf
['vnf_name']
1576 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1577 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1583 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1585 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1586 vnf
['uuid']=vnf_db
[0]['uuid']
1587 vnf
['description']=vnf_db
[0]['description']
1589 # get external interfaces
1590 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1591 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1592 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1593 for ext_iface
in ext_ifaces
:
1594 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1596 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1598 #2: Insert net_key and ip_address at every vnf interface
1599 for net_name
,net
in scenario
["networks"].iteritems():
1600 net_type_bridge
=False
1602 for iface_dict
in net
["interfaces"]:
1603 logger
.debug("Iface_dict %s", iface_dict
)
1604 vnf
= iface_dict
["vnf"]
1605 iface
= iface_dict
["vnf_interface"]
1606 if vnf
not in scenario
["vnfs"]:
1607 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1608 #logger.debug(error_text)
1609 raise NfvoException(error_text
, HTTP_Not_Found
)
1610 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1611 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1612 #logger.debug(error_text)
1613 raise NfvoException(error_text
, HTTP_Bad_Request
)
1614 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1615 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1616 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1617 #logger.debug(error_text)
1618 raise NfvoException(error_text
, HTTP_Bad_Request
)
1619 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1620 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['ip_address'] = iface_dict
.get('ip_address',None)
1621 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1622 if iface_type
=='mgmt' or iface_type
=='bridge':
1623 net_type_bridge
= True
1625 net_type_data
= True
1626 if net_type_bridge
and net_type_data
:
1627 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1628 #logger.debug(error_text)
1629 raise NfvoException(error_text
, HTTP_Bad_Request
)
1630 elif net_type_bridge
:
1633 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1635 if ("implementation" in net
):
1636 if (type_
== "bridge" and net
["implementation"] == "underlay"):
1637 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at 'network':'%s'" % (net_name
)
1638 #logger.debug(error_text)
1639 raise NfvoException(error_text
, HTTP_Bad_Request
)
1640 elif (type_
<> "bridge" and net
["implementation"] == "overlay"):
1641 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at 'network':'%s'" % (net_name
)
1642 #logger.debug(error_text)
1643 raise NfvoException(error_text
, HTTP_Bad_Request
)
1644 net
.pop("implementation")
1646 if (type_
== "data" and net
["type"] == "e-line"):
1647 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type 'e-line' at 'network':'%s'" % (net_name
)
1648 #logger.debug(error_text)
1649 raise NfvoException(error_text
, HTTP_Bad_Request
)
1650 elif (type_
== "ptp" and net
["type"] == "e-lan"):
1654 net
['name'] = net_name
1655 net
['external'] = net
.get('external', False)
1657 #3: insert at database
1658 scenario
["nets"] = scenario
["networks"]
1659 scenario
['tenant_id'] = tenant_id
1660 scenario_id
= mydb
.new_scenario2(scenario
)
1664 '''Takes dict d and updates it with the values in dict u.'''
1665 '''It merges all depth levels'''
1666 for k
, v
in u
.iteritems():
1667 if isinstance(v
, collections
.Mapping
):
1668 r
= update(d
.get(k
, {}), v
)
1674 def create_instance(mydb
, tenant_id
, instance_dict
):
1675 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1676 #logger.debug("Creating instance...")
1677 scenario
= instance_dict
["scenario"]
1679 #find main datacenter
1681 datacenter
= instance_dict
.get("datacenter")
1682 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1683 myvims
[default_datacenter_id
] = vim
1684 #myvim_tenant = myvim['tenant_id']
1685 # default_datacenter_name = vim['name']
1686 default_datacenter_tenant_id
= vim
['config']['datacenter_tenant_id'] #TODO review
1689 #print "Checking that the scenario exists and getting the scenario dictionary"
1690 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1692 #logger.debug(">>>>>>> Dictionaries before merging")
1693 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1694 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1696 scenarioDict
['datacenter_tenant_id'] = default_datacenter_tenant_id
1697 scenarioDict
['datacenter_id'] = default_datacenter_id
1699 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1700 auxNetDict
['scenario'] = {}
1702 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1703 instance_name
= instance_dict
["name"]
1704 instance_description
= instance_dict
.get("description")
1706 #0 check correct parameters
1707 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1709 for scenario_net
in scenarioDict
['nets']:
1710 if net_name
== scenario_net
["name"]:
1714 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1715 if "sites" not in net_instance_desc
:
1716 net_instance_desc
["sites"] = [ {} ]
1717 site_without_datacenter_field
= False
1718 for site
in net_instance_desc
["sites"]:
1719 if site
.get("datacenter"):
1720 if site
["datacenter"] not in myvims
:
1721 #Add this datacenter to myvims
1722 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1724 site
["datacenter"] = d
#change name to id
1726 if site_without_datacenter_field
:
1727 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1728 site_without_datacenter_field
= True
1729 site
["datacenter"] = default_datacenter_id
#change name to id
1731 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
1733 for scenario_vnf
in scenarioDict
['vnfs']:
1734 if vnf_name
== scenario_vnf
['name']:
1738 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
1739 if "datacenter" in vnf_instance_desc
:
1740 #Add this datacenter to myvims
1741 if vnf_instance_desc
["datacenter"] not in myvims
:
1742 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
1744 scenario_vnf
["datacenter"] = d
#change name to id
1745 #0.1 parse cloud-config parameters
1746 cloud_config
= scenarioDict
.get("cloud-config", {})
1747 if instance_dict
.get("cloud-config"):
1748 cloud_config
.update( instance_dict
["cloud-config"])
1749 if not cloud_config
:
1752 scenarioDict
["cloud-config"] = cloud_config
1753 unify_cloud_config(cloud_config
)
1755 #0.2 merge instance information into scenario
1756 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
1757 #However, this is not possible yet.
1758 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1759 for scenario_net
in scenarioDict
['nets']:
1760 if net_name
== scenario_net
["name"]:
1761 if 'ip-profile' in net_instance_desc
:
1762 ipprofile
= net_instance_desc
['ip-profile']
1763 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
1764 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
1765 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
1766 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
1767 if 'dhcp' in ipprofile
:
1768 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
1769 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
1770 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
1771 del ipprofile
['dhcp']
1772 if 'ip_profile' not in scenario_net
:
1773 scenario_net
['ip_profile'] = ipprofile
1775 update(scenario_net
['ip_profile'],ipprofile
)
1776 for interface
in net_instance_desc
.get('interfaces', () ):
1777 if 'ip_address' in interface
:
1778 for vnf
in scenarioDict
['vnfs']:
1779 if interface
['vnf'] == vnf
['name']:
1780 for vnf_interface
in vnf
['interfaces']:
1781 if interface
['vnf_interface'] == vnf_interface
['external_name']:
1782 vnf_interface
['ip_address']=interface
['ip_address']
1784 #logger.debug(">>>>>>>> Merged dictionary")
1785 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
1788 #1. Creating new nets (sce_nets) in the VIM"
1789 for sce_net
in scenarioDict
['nets']:
1790 sce_net
["vim_id_sites"]={}
1791 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
1792 net_name
= descriptor_net
.get("vim-network-name")
1793 auxNetDict
['scenario'][sce_net
['uuid']] = {}
1795 sites
= descriptor_net
.get("sites", [ {} ])
1797 if site
.get("datacenter"):
1798 vim
= myvims
[ site
["datacenter"] ]
1799 datacenter_id
= site
["datacenter"]
1801 vim
= myvims
[ default_datacenter_id
]
1802 datacenter_id
= default_datacenter_id
1804 net_type
= sce_net
['type']
1805 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
1806 if sce_net
["external"]:
1808 net_name
= sce_net
["name"]
1809 if "netmap-use" in site
or "netmap-create" in site
:
1810 create_network
= False
1811 lookfor_network
= False
1812 if "netmap-use" in site
:
1813 lookfor_network
= True
1814 if utils
.check_valid_uuid(site
["netmap-use"]):
1815 filter_text
= "scenario id '%s'" % site
["netmap-use"]
1816 lookfor_filter
["id"] = site
["netmap-use"]
1818 filter_text
= "scenario name '%s'" % site
["netmap-use"]
1819 lookfor_filter
["name"] = site
["netmap-use"]
1820 if "netmap-create" in site
:
1821 create_network
= True
1822 net_vim_name
= net_name
1823 if site
["netmap-create"]:
1824 net_vim_name
= site
["netmap-create"]
1826 elif sce_net
['vim_id'] != None:
1827 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
1828 create_network
= False
1829 lookfor_network
= True
1830 lookfor_filter
["id"] = sce_net
['vim_id']
1831 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
1832 #look for network at datacenter and return error
1834 #There is not a netmap, look at datacenter for a net with this name and create if not found
1835 create_network
= True
1836 lookfor_network
= True
1837 lookfor_filter
["name"] = sce_net
["name"]
1838 net_vim_name
= sce_net
["name"]
1839 filter_text
= "scenario name '%s'" % sce_net
["name"]
1842 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
1843 net_name
= net_name
[:255] #limit length
1844 net_vim_name
= net_name
1845 create_network
= True
1846 lookfor_network
= False
1849 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
1850 if len(vim_nets
) > 1:
1851 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1852 elif len(vim_nets
) == 0:
1853 if not create_network
:
1854 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1856 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
1858 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
1859 create_network
= False
1861 #if network is not external
1862 network_id
= vim
.new_network(net_vim_name
, net_type
, sce_net
.get('ip_profile',None))
1863 sce_net
["vim_id_sites"][datacenter_id
] = network_id
1864 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = network_id
1865 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':network_id
})
1866 sce_net
["created"] = True
1868 #2. Creating new nets (vnf internal nets) in the VIM"
1869 #For each vnf net, we create it and we add it to instanceNetlist.
1870 for sce_vnf
in scenarioDict
['vnfs']:
1871 for net
in sce_vnf
['nets']:
1872 if sce_vnf
.get("datacenter"):
1873 vim
= myvims
[ sce_vnf
["datacenter"] ]
1874 datacenter_id
= sce_vnf
["datacenter"]
1876 vim
= myvims
[ default_datacenter_id
]
1877 datacenter_id
= default_datacenter_id
1878 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
1879 net_name
= descriptor_net
.get("name")
1881 net_name
= "%s.%s" %(instance_name
, net
["name"])
1882 net_name
= net_name
[:255] #limit length
1883 net_type
= net
['type']
1884 network_id
= vim
.new_network(net_name
, net_type
, net
.get('ip_profile',None))
1885 net
['vim_id'] = network_id
1886 if sce_vnf
['uuid'] not in auxNetDict
:
1887 auxNetDict
[sce_vnf
['uuid']] = {}
1888 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1889 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1890 net
["created"] = True
1893 #print "auxNetDict:"
1894 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1896 #3. Creating new vm instances in the VIM
1897 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1898 for sce_vnf
in scenarioDict
['vnfs']:
1899 if sce_vnf
.get("datacenter"):
1900 vim
= myvims
[ sce_vnf
["datacenter"] ]
1901 datacenter_id
= sce_vnf
["datacenter"]
1903 vim
= myvims
[ default_datacenter_id
]
1904 datacenter_id
= default_datacenter_id
1905 sce_vnf
["datacenter_id"] = datacenter_id
1906 sce_vnf
["datacenter_tenant_id"] = vim
['config']['datacenter_tenant_id']
1908 for vm
in sce_vnf
['vms']:
1911 myVMDict
['name'] = "%s.%s.%d" % (instance_name
,sce_vnf
['name'],i
)
1912 myVMDict
['description'] = myVMDict
['name'][0:99]
1914 # myVMDict['start'] = "no"
1915 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1916 #create image at vim in case it not exist
1917 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1918 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
1919 vm
['vim_image_id'] = image_id
1921 #create flavor at vim in case it not exist
1922 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1923 if flavor_dict
['extended']!=None:
1924 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1925 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
1926 vm
['vim_flavor_id'] = flavor_id
1928 myVMDict
['imageRef'] = vm
['vim_image_id']
1929 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1930 myVMDict
['networks'] = []
1931 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
1932 for iface
in vm
['interfaces']:
1934 if iface
['type']=="data":
1935 netDict
['type'] = iface
['model']
1936 elif "model" in iface
and iface
["model"]!=None:
1937 netDict
['model']=iface
['model']
1938 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1939 #discover type of interface looking at flavor
1940 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1941 for flavor_iface
in numa
.get('interfaces',[]):
1942 if flavor_iface
.get('name') == iface
['internal_name']:
1943 if flavor_iface
['dedicated'] == 'yes':
1944 netDict
['type']="PF" #passthrough
1945 elif flavor_iface
['dedicated'] == 'no':
1946 netDict
['type']="VF" #siov
1947 elif flavor_iface
['dedicated'] == 'yes:sriov':
1948 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1949 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1951 netDict
["use"]=iface
['type']
1952 if netDict
["use"]=="data" and not netDict
.get("type"):
1953 #print "netDict", netDict
1954 #print "iface", iface
1955 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'])
1956 if flavor_dict
.get('extended')==None:
1957 raise NfvoException(e_text
+ "After database migration some information is not available. \
1958 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1960 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1961 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1962 netDict
["type"]="virtual"
1963 if "vpci" in iface
and iface
["vpci"] is not None:
1964 netDict
['vpci'] = iface
['vpci']
1965 if "mac" in iface
and iface
["mac"] is not None:
1966 netDict
['mac_address'] = iface
['mac']
1967 netDict
['name'] = iface
['internal_name']
1968 if iface
['net_id'] is None:
1969 for vnf_iface
in sce_vnf
["interfaces"]:
1972 if vnf_iface
['interface_id']==iface
['uuid']:
1973 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
1976 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1977 #skip bridge ifaces not connected to any net
1978 #if 'net_id' not in netDict or netDict['net_id']==None:
1980 myVMDict
['networks'].append(netDict
)
1981 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1982 #print myVMDict['name']
1983 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1984 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1985 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1986 vm_id
= vim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1987 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'], cloud_config
= cloud_config
)
1988 vm
['vim_id'] = vm_id
1989 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1990 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1991 for net
in myVMDict
['networks']:
1993 for iface
in vm
['interfaces']:
1994 if net
["name"]==iface
["internal_name"]:
1995 iface
["vim_id"]=net
["vim_id"]
1997 logger
.debug("create_instance Deployment done")
1998 print yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)
1999 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2000 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
2001 return mydb
.get_instance_scenario(instance_id
)
2002 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2003 message
= rollback(mydb
, myvims
, rollbackList
)
2004 if isinstance(e
, db_base_Exception
):
2005 error_text
= "database Exception"
2006 elif isinstance(e
, vimconn
.vimconnException
):
2007 error_text
= "VIM Exception"
2009 error_text
= "Exception"
2010 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2011 #logger.error("create_instance: %s", error_text)
2012 raise NfvoException(error_text
, e
.http_code
)
2014 def delete_instance(mydb
, tenant_id
, instance_id
):
2015 #print "Checking that the instance_id exists and getting the instance dictionary"
2016 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2017 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2018 tenant_id
= instanceDict
["tenant_id"]
2019 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2021 vims
= get_vim(mydb
, tenant_id
, instanceDict
['datacenter_id'])
2023 logger
.error("!!!!!! nfvo.delete_instance() datacenter not found!!!!")
2026 myvim
= vims
.values()[0]
2027 except NfvoException
as e
:
2028 logger
.error("!!!!!! nfvo.delete_instance() datacenter Exception!!!! " + str(e
))
2032 #1. Delete from Database
2034 #result,c = mydb.delete_row_by_id('instance_scenarios', instance_id, nfvo_tenant)
2035 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2039 error_msg
= "Not possible to delete VIM VMs and networks. Datacenter not found at database!!!"
2045 for sce_vnf
in instanceDict
['vnfs']:
2048 for vm
in sce_vnf
['vms']:
2050 myvim
.delete_vminstance(vm
['vim_vm_id'])
2051 except vimconn
.vimconnNotFoundException
as e
:
2052 error_msg
+="\n VM id={} not found at VIM".format(vm
['vim_vm_id'])
2053 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2054 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2055 except vimconn
.vimconnException
as e
:
2056 error_msg
+="\n Error: " + e
.http_code
+ " VM id=" + vm
['vim_vm_id']
2057 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s': %s",
2058 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2062 for net
in instanceDict
['nets']:
2063 if not net
['created']:
2064 continue #skip not created nets
2068 myvim
.delete_network(net
['vim_net_id'])
2069 except vimconn
.vimconnNotFoundException
as e
:
2070 error_msg
+="\n NET id={} not found at VIM".format(net
['vim_net_id'])
2071 logger
.warn("NET '%s', VIM id '%s', from VNF_id '%s' not found",
2072 net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'])
2073 except vimconn
.vimconnException
as e
:
2074 error_msg
+="\n Error: " + e
.http_code
+ " Net id=" + net
['vim_vm_id']
2075 logger
.error("Error %d deleting NET '%s', VIM id '%s', from VNF_id '%s': %s",
2076 e
.http_code
, net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'], str(e
))
2077 if len(error_msg
)>0:
2078 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2080 return 'instance ' + message
+ ' deleted'
2082 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2083 '''Refreshes a scenario instance. It modifies instanceDict'''
2085 - 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
2088 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2089 #print "nfvo.refresh_instance begins"
2090 #print json.dumps(instanceDict, indent=4)
2092 #print "Getting the VIM URL and the VIM tenant_id"
2093 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2095 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2096 myvim
= vims
.values()[0]
2098 # 1. Getting VIM vm and net list
2099 vms_updated
= [] #List of VM instance uuids in openmano that were updated
2102 for sce_vnf
in instanceDict
['vnfs']:
2103 for vm
in sce_vnf
['vms']:
2104 vm_list
.append(vm
['vim_vm_id'])
2105 vms_notupdated
.append(vm
["uuid"])
2107 nets_updated
= [] #List of VM instance uuids in openmano that were updated
2110 for net
in instanceDict
['nets']:
2111 net_list
.append(net
['vim_net_id'])
2112 nets_notupdated
.append(net
["uuid"])
2115 # 1. Getting the status of all VMs
2116 vm_dict
= myvim
.refresh_vms_status(vm_list
)
2118 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2119 for sce_vnf
in instanceDict
['vnfs']:
2120 for vm
in sce_vnf
['vms']:
2121 vm_id
= vm
['vim_vm_id']
2122 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
2123 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2124 has_mgmt_iface
= False
2125 for iface
in vm
["interfaces"]:
2126 if iface
["type"]=="mgmt":
2127 has_mgmt_iface
= True
2128 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
2129 vm_dict
[vm_id
]['status'] = "ACTIVE"
2130 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'):
2131 vm
['status'] = vm_dict
[vm_id
]['status']
2132 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
2133 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
2134 # 2.1. Update in openmano DB the VMs whose status changed
2136 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
2137 vms_notupdated
.remove(vm
["uuid"])
2139 vms_updated
.append(vm
["uuid"])
2140 except db_base_Exception
as e
:
2141 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2142 # 2.2. Update in openmano DB the interface VMs
2143 for interface
in interfaces
:
2144 #translate from vim_net_id to instance_net_id
2146 for net
in instanceDict
['nets']:
2147 if net
["vim_net_id"] == interface
["vim_net_id"]:
2148 network_id_list
.append(net
["uuid"])
2149 if not network_id_list
:
2151 del interface
["vim_net_id"]
2153 for network_id
in network_id_list
:
2154 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
2155 except db_base_Exception
as e
:
2156 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
2158 # 3. Getting the status of all nets
2159 net_dict
= myvim
.refresh_nets_status(net_list
)
2161 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2162 # TODO: update nets inside a vnf
2163 for net
in instanceDict
['nets']:
2164 net_id
= net
['vim_net_id']
2165 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'):
2166 net
['status'] = net_dict
[net_id
]['status']
2167 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
2168 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
2169 # 5.1. Update in openmano DB the nets whose status changed
2171 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
2172 nets_notupdated
.remove(net
["uuid"])
2174 nets_updated
.append(net
["uuid"])
2175 except db_base_Exception
as e
:
2176 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2177 except vimconn
.vimconnException
as e
:
2178 #logger.error("VIM exception %s %s", type(e).__name__, str(e))
2179 raise NfvoException(str(e
), e
.http_code
)
2181 # Returns appropriate output
2182 #print "nfvo.refresh_instance finishes"
2183 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2184 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
2185 instance_id
= instanceDict
['uuid']
2186 if len(vms_notupdated
)+len(nets_notupdated
)>0:
2187 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
2188 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
2190 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2192 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2193 #print "Checking that the instance_id exists and getting the instance dictionary"
2194 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2195 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2197 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2198 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2200 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2201 myvim
= vims
.values()[0]
2204 input_vnfs
= action_dict
.pop("vnfs", [])
2205 input_vms
= action_dict
.pop("vms", [])
2206 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2210 for sce_vnf
in instanceDict
['vnfs']:
2211 for vm
in sce_vnf
['vms']:
2212 if not action_over_all
:
2213 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2214 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2217 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2218 if "console" in action_dict
:
2219 if not global_config
["http_console_proxy"]:
2220 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2221 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2222 protocol
=data
["protocol"],
2223 ip
= data
["server"],
2224 port
= data
["port"],
2225 suffix
= data
["suffix"]),
2229 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2230 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2231 "description": "this console is only reachable by local interface",
2236 #print "console data", data
2238 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2239 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2240 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2241 protocol
=data
["protocol"],
2242 ip
= global_config
["http_console_host"],
2243 port
= console_thread
.port
,
2244 suffix
= data
["suffix"]),
2248 except NfvoException
as e
:
2249 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2253 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2255 except vimconn
.vimconnException
as e
:
2256 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2259 if vm_ok
==0: #all goes wrong
2264 def create_or_use_console_proxy_thread(console_server
, console_port
):
2265 #look for a non-used port
2266 console_thread_key
= console_server
+ ":" + str(console_port
)
2267 if console_thread_key
in global_config
["console_thread"]:
2268 #global_config["console_thread"][console_thread_key].start_timeout()
2269 return global_config
["console_thread"][console_thread_key
]
2271 for port
in global_config
["console_port_iterator"]():
2272 #print "create_or_use_console_proxy_thread() port:", port
2273 if port
in global_config
["console_ports"]:
2276 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2278 global_config
["console_thread"][console_thread_key
] = clithread
2279 global_config
["console_ports"][port
] = console_thread_key
2281 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2282 #port used, try with onoher
2284 except cli
.ConsoleProxyException
as e
:
2285 raise NfvoException(str(e
), HTTP_Bad_Request
)
2286 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2288 def check_tenant(mydb
, tenant_id
):
2289 '''check that tenant exists at database'''
2290 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2292 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2295 def new_tenant(mydb
, tenant_dict
):
2296 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2299 def delete_tenant(mydb
, tenant
):
2300 #get nfvo_tenant info
2302 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2303 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2304 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2306 def new_datacenter(mydb
, datacenter_descriptor
):
2307 if "config" in datacenter_descriptor
:
2308 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2309 #Check that datacenter-type is correct
2310 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2313 module
= "vimconn_" + datacenter_type
2314 module_info
= imp
.find_module(module
)
2315 except (IOError, ImportError):
2316 if module_info
and module_info
[0]:
2317 file.close(module_info
[0])
2318 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2320 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2321 return datacenter_id
2323 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2324 #obtain data, check that only one exist
2325 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2327 datacenter_id
= datacenter
['uuid']
2328 where
={'uuid': datacenter
['uuid']}
2329 if "config" in datacenter_descriptor
:
2330 if datacenter_descriptor
['config']!=None:
2332 new_config_dict
= datacenter_descriptor
["config"]
2335 for k
in new_config_dict
:
2336 if new_config_dict
[k
]==None:
2339 config_dict
= yaml
.load(datacenter
["config"])
2340 config_dict
.update(new_config_dict
)
2344 except Exception as e
:
2345 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2346 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2347 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2348 return datacenter_id
2350 def delete_datacenter(mydb
, datacenter
):
2351 #get nfvo_tenant info
2352 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2353 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2354 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2356 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None):
2357 #get datacenter info
2358 if utils
.check_valid_uuid(datacenter
):
2359 vims
= get_vim(mydb
, datacenter_id
=datacenter
, vim_tenant_name
=vim_tenant_name
, vim_user
=vim_username
, vim_passwd
=vim_password
)
2361 vims
= get_vim(mydb
, datacenter_name
=datacenter
, vim_tenant_name
=vim_tenant_name
, vim_user
=vim_username
, vim_passwd
=vim_password
)
2363 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2365 #print "nfvo.datacenter_action() error. Several datacenters found"
2366 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2368 datacenter_id
=vims
.keys()[0]
2369 myvim
=vims
[datacenter_id
]
2370 datacenter_name
=myvim
["name"]
2372 create_vim_tenant
=True if vim_tenant_id
==None and vim_tenant_name
==None else False
2374 #get nfvo_tenant info
2375 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2376 if vim_tenant_name
==None:
2377 vim_tenant_name
=tenant_dict
['name']
2379 #check that this association does not exist before
2380 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2381 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2382 if len(tenants_datacenters
)>0:
2383 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2385 vim_tenant_id_exist_atdb
=False
2386 if not create_vim_tenant
:
2387 where_
={"datacenter_id": datacenter_id
}
2388 if vim_tenant_id
!=None:
2389 where_
["vim_tenant_id"] = vim_tenant_id
2390 if vim_tenant_name
!=None:
2391 where_
["vim_tenant_name"] = vim_tenant_name
2392 #check if vim_tenant_id is already at database
2393 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2394 if len(datacenter_tenants_dict
)>=1:
2395 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2396 vim_tenant_id_exist_atdb
=True
2397 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2399 datacenter_tenants_dict
= {}
2400 #insert at table datacenter_tenants
2401 else: #if vim_tenant_id==None:
2402 #create tenant at VIM if not provided
2404 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2405 except vimconn
.vimconnException
as e
:
2406 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2407 datacenter_tenants_dict
= {}
2408 datacenter_tenants_dict
["created"]="true"
2410 #fill datacenter_tenants table
2411 if not vim_tenant_id_exist_atdb
:
2412 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2413 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2414 datacenter_tenants_dict
["user"] = vim_username
2415 datacenter_tenants_dict
["passwd"] = vim_password
2416 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2417 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2418 datacenter_tenants_dict
["uuid"] = id_
2420 #fill tenants_datacenters table
2421 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2422 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2423 return datacenter_id
2425 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2426 #get datacenter info
2427 if utils
.check_valid_uuid(datacenter
):
2428 vims
= get_vim(mydb
, datacenter_id
=datacenter
)
2430 vims
= get_vim(mydb
, datacenter_name
=datacenter
)
2432 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2434 #print "nfvo.datacenter_action() error. Several datacenters found"
2435 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2436 datacenter_id
=vims
.keys()[0]
2437 myvim
=vims
[datacenter_id
]
2439 #get nfvo_tenant info
2440 if not tenant_id
or tenant_id
=="any":
2443 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2444 tenant_uuid
= tenant_dict
['uuid']
2446 #check that this association exist before
2447 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2449 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2450 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2451 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2452 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2454 #delete this association
2455 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2457 #get vim_tenant info and deletes
2459 for tenant_datacenter_item
in tenant_datacenter_list
:
2460 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2461 #try to delete vim:tenant
2463 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2464 if vim_tenant_dict
['created']=='true':
2465 #delete tenant at VIM if created by NFVO
2467 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2468 except vimconn
.vimconnException
as e
:
2469 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2470 logger
.warn(warning
)
2471 except db_base_Exception
as e
:
2472 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2473 pass #the error will be caused because dependencies, vim_tenant can not be deleted
2475 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2477 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2479 #get datacenter info
2480 if utils
.check_valid_uuid(datacenter
):
2481 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2483 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2485 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2487 #print "nfvo.datacenter_action() error. Several datacenters found"
2488 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2489 datacenter_id
=vims
.keys()[0]
2490 myvim
=vims
[datacenter_id
]
2492 if 'net-update' in action_dict
:
2494 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2496 except vimconn
.vimconnException
as e
:
2497 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2498 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2499 #update nets Change from VIM format to NFVO format
2502 net_nfvo
={'datacenter_id': datacenter_id
}
2503 net_nfvo
['name'] = net
['name']
2504 #net_nfvo['description']= net['name']
2505 net_nfvo
['vim_net_id'] = net
['id']
2506 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2507 net_nfvo
['shared'] = net
['shared']
2508 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2509 net_list
.append(net_nfvo
)
2510 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2511 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2513 elif 'net-edit' in action_dict
:
2514 net
= action_dict
['net-edit'].pop('net')
2515 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2516 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2517 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2519 elif 'net-delete' in action_dict
:
2520 net
= action_dict
['net-deelte'].get('net')
2521 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2522 result
= mydb
.delete_row(FROM
='datacenter_nets',
2523 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2527 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2529 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2530 #get datacenter info
2531 if utils
.check_valid_uuid(datacenter
):
2532 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2534 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2536 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2538 #print "nfvo.datacenter_action() error. Several datacenters found"
2539 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2540 datacenter_id
=vims
.keys()[0]
2542 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2543 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2544 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2547 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2548 #get datacenter info
2549 if utils
.check_valid_uuid(datacenter
):
2550 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2552 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2554 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2556 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2557 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2558 datacenter_id
=vims
.keys()[0]
2559 myvim
=vims
[datacenter_id
]
2562 action_dict
= action_dict
["netmap"]
2563 if 'vim_id' in action_dict
:
2564 filter_dict
["id"] = action_dict
['vim_id']
2565 if 'vim_name' in action_dict
:
2566 filter_dict
["name"] = action_dict
['vim_name']
2568 filter_dict
["shared"] = True
2571 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
2572 except vimconn
.vimconnException
as e
:
2573 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
2574 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2575 if len(vim_nets
)>1 and action_dict
:
2576 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
2577 elif len(vim_nets
)==0: # and action_dict:
2578 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
2580 for net
in vim_nets
:
2581 net_nfvo
={'datacenter_id': datacenter_id
}
2582 if action_dict
and "name" in action_dict
:
2583 net_nfvo
['name'] = action_dict
['name']
2585 net_nfvo
['name'] = net
['name']
2586 #net_nfvo['description']= net['name']
2587 net_nfvo
['vim_net_id'] = net
['id']
2588 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2589 net_nfvo
['shared'] = net
['shared']
2590 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2592 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2593 net_nfvo
["status"] = "OK"
2594 net_nfvo
["uuid"] = net_id
2595 except db_base_Exception
as e
:
2599 net_nfvo
["status"] = "FAIL: " + str(e
)
2600 net_list
.append(net_nfvo
)
2603 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2604 #get datacenter info
2605 if utils
.check_valid_uuid(datacenter
):
2606 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2608 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2610 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2612 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2613 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2614 datacenter_id
=vims
.keys()[0]
2615 myvim
=vims
[datacenter_id
]
2618 if utils
.check_valid_uuid(name
):
2619 filter_dict
["id"] = name
2621 filter_dict
["name"] = name
2623 if item
=="networks":
2624 #filter_dict['tenant_id'] = myvim['tenant_id']
2625 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2626 elif item
=="tenants":
2627 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2629 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2630 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
2631 if name
and len(content
)==1:
2632 return {item
[:-1]: content
[0]}
2633 elif name
and len(content
)==0:
2634 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
2637 return {item
: content
}
2638 except vimconn
.vimconnException
as e
:
2639 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
2640 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
2642 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
2643 #get datacenter info
2644 if tenant_id
== "any":
2647 if utils
.check_valid_uuid(datacenter
):
2648 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2650 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2652 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2654 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2655 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2656 datacenter_id
=vims
.keys()[0]
2657 myvim
=vims
[datacenter_id
]
2659 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2660 logger
.debug("vim_action_delete vim response: " + str(content
))
2661 items
= content
.values()[0]
2662 if type(items
)==list and len(items
)==0:
2663 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
2664 elif type(items
)==list and len(items
)>1:
2665 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
2666 else: # it is a dict
2667 item_id
= items
["id"]
2668 item_name
= str(items
.get("name"))
2671 if item
=="networks":
2672 content
= myvim
.delete_network(item_id
)
2673 elif item
=="tenants":
2674 content
= myvim
.delete_tenant(item_id
)
2676 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2677 except vimconn
.vimconnException
as e
:
2678 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
2679 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
2681 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
2683 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2684 #get datacenter info
2685 print "vim_action_create descriptor", descriptor
2686 if tenant_id
== "any":
2689 if utils
.check_valid_uuid(datacenter
):
2690 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2692 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2694 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2696 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2697 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2698 datacenter_id
=vims
.keys()[0]
2699 myvim
=vims
[datacenter_id
]
2702 if item
=="networks":
2703 net
= descriptor
["network"]
2704 net_name
= net
.pop("name")
2705 net_type
= net
.pop("type", "bridge")
2706 net_public
= net
.pop("shared", False)
2707 net_ipprofile
= net
.pop("ip_profile", None)
2708 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, **net
)
2709 elif item
=="tenants":
2710 tenant
= descriptor
["tenant"]
2711 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2713 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2714 except vimconn
.vimconnException
as e
:
2715 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
2717 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)