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 vim_images
= vim
.get_image_list(filter_dict
)
288 if len(vim_images
) > 1:
289 raise NfvoException("More than one candidate VIM image found for filter: " + str(filter_dict
), HTTP_Conflict
)
290 elif len(vim_nets
) == 0:
291 raise NfvoException("Image not found at VIM with filter: '%s'", str(filter_dict
))
293 image_vim_id
= vim_images
[0].id
295 except vimconn
.vimconnNotFoundException
as e
:
296 #Create the image in VIM
298 image_vim_id
= vim
.new_image(image_dict
)
299 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
301 except vimconn
.vimconnException
as e
:
303 logger
.error("Error creating image at VIM: %s", str(e
))
305 image_vim_id
= str(e
)
306 logger
.warn("Error creating image at VIM: %s", str(e
))
308 except vimconn
.vimconnException
as e
:
309 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
310 image_vim_id
= str(e
)
312 #if we reach here, the image has been created or existed
314 #add new vim_id at datacenters_images
315 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
316 elif image_db
[0]["vim_id"]!=image_vim_id
:
317 #modify existing vim_id at datacenters_images
318 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
320 return image_vim_id
if only_create_at_vim
else image_mano_id
322 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
323 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
324 'ram':flavor_dict
.get('ram'),
325 'vcpus':flavor_dict
.get('vcpus'),
327 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
328 del flavor_dict
['extended']
329 if 'extended' in flavor_dict
:
330 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
332 #look if flavor exist
333 if only_create_at_vim
:
334 flavor_mano_id
= flavor_dict
['uuid']
336 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
338 flavor_mano_id
= flavors
[0]['uuid']
341 #create one by one the images of aditional disks
342 dev_image_list
=[] #list of images
343 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
345 for device
in flavor_dict
['extended'].get('devices',[]):
346 if "image" not in device
or "image name" not in device
:
349 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
350 image_dict
['universal_name']=device
.get('image name')
351 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
352 image_dict
['location']=device
.get('image')
353 image_dict
['checksum']=device
.get('image checksum')
354 image_metadata_dict
= device
.get('image metadata', None)
355 image_metadata_str
= None
356 if image_metadata_dict
!= None:
357 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
358 image_dict
['metadata']=image_metadata_str
359 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
360 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
361 dev_image_list
.append(image_id
)
363 temp_flavor_dict
['name'] = flavor_dict
['name']
364 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
365 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
366 flavor_mano_id
= content
367 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
368 #create flavor at every vim
369 if 'uuid' in flavor_dict
:
370 del flavor_dict
['uuid']
372 for vim_id
,vim
in vims
.items():
373 flavor_created
="false"
375 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
376 #look at VIM if this flavor exist SKIPPED
377 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
379 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
383 #Create the flavor in VIM
384 #Translate images at devices from MANO id to VIM id
385 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
386 #make a copy of original devices
388 for device
in flavor_dict
["extended"].get("devices",[]):
391 devices_original
.append(dev
)
392 if 'image' in device
:
394 if 'image metadata' in device
:
395 del device
['image metadata']
397 for index
in range(0,len(devices_original
)) :
398 device
=devices_original
[index
]
399 if "image" not in device
or "image name" not in device
:
402 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
403 image_dict
['universal_name']=device
.get('image name')
404 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
405 image_dict
['location']=device
.get('image')
406 image_dict
['checksum']=device
.get('image checksum')
407 image_metadata_dict
= device
.get('image metadata', None)
408 image_metadata_str
= None
409 if image_metadata_dict
!= None:
410 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
411 image_dict
['metadata']=image_metadata_str
412 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
413 image_dict
["uuid"]=image_mano_id
414 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
415 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
418 #check that this vim_id exist in VIM, if not create
419 flavor_vim_id
=flavor_db
[0]["vim_id"]
421 vim
.get_flavor(flavor_vim_id
)
422 continue #flavor exist
423 except vimconn
.vimconnException
:
425 #create flavor at vim
426 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
428 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
429 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
430 flavor_created
="true"
431 except vimconn
.vimconnException
as e
:
433 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
435 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
437 #if reach here the flavor has been create or exist
438 if len(flavor_db
)==0:
439 #add new vim_id at datacenters_flavors
440 mydb
.new_row('datacenters_flavors', {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
, 'created':flavor_created
})
441 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
442 #modify existing vim_id at datacenters_flavors
443 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
445 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
447 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
450 # Step 1. Check the VNF descriptor
451 check_vnf_descriptor(vnf_descriptor
)
452 # Step 2. Check tenant exist
453 if tenant_id
!= "any":
454 check_tenant(mydb
, tenant_id
)
455 if "tenant_id" in vnf_descriptor
["vnf"]:
456 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
457 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
460 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
461 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
462 vims
= get_vim(mydb
, tenant_id
)
466 # Step 4. Review the descriptor and add missing fields
467 #print vnf_descriptor
468 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
469 vnf_name
= vnf_descriptor
['vnf']['name']
470 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
471 if "physical" in vnf_descriptor
['vnf']:
472 del vnf_descriptor
['vnf']['physical']
473 #print vnf_descriptor
474 # Step 5. Check internal connections
475 # TODO: to be moved to step 1????
476 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
477 for ic
in internal_connections
:
478 if len(ic
['elements'])>2 and ic
['type']=='ptp':
479 raise NfvoException("Mismatch 'type':'ptp' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'data'".format(len(ic
), ic
['name']),
481 elif len(ic
['elements'])==2 and ic
['type']=='data':
482 raise NfvoException("Mismatch 'type':'data' with 2 elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'ptp'".format(ic
['name']),
485 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
486 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
487 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
489 #For each VNFC, we add it to the VNFCDict and we create a flavor.
490 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
491 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
493 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
494 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
496 VNFCitem
["name"] = vnfc
['name']
497 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
499 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
502 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
503 myflavorDict
["description"] = VNFCitem
["description"]
504 myflavorDict
["ram"] = vnfc
.get("ram", 0)
505 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
506 myflavorDict
["disk"] = vnfc
.get("disk", 1)
507 myflavorDict
["extended"] = {}
509 devices
= vnfc
.get("devices")
511 myflavorDict
["extended"]["devices"] = devices
514 # 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
515 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
517 # Previous code has been commented
518 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
519 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
520 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
521 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
523 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
525 # print "Error creating flavor: unknown processor model. Rollback successful."
526 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
528 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
529 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
531 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
532 myflavorDict
['extended']['numas'] = vnfc
['numas']
536 # Step 6.2 New flavors are created in the VIM
537 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
539 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
540 VNFCitem
["flavor_id"] = flavor_id
541 VNFCDict
[vnfc
['name']] = VNFCitem
543 logger
.debug("Creating new images in the VIM for each VNFC")
544 # Step 6.3 New images are created in the VIM
545 #For each VNFC, we must create the appropriate image.
546 #This "for" loop might be integrated with the previous one
547 #In case this integration is made, the VNFCDict might become a VNFClist.
548 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
549 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
551 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
552 image_dict
['universal_name']=vnfc
.get('image name')
553 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
554 image_dict
['location']=vnfc
.get('VNFC image')
555 image_dict
['checksum']=vnfc
.get('image checksum')
556 image_metadata_dict
= vnfc
.get('image metadata', None)
557 image_metadata_str
= None
558 if image_metadata_dict
is not None:
559 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
560 image_dict
['metadata']=image_metadata_str
561 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
562 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
563 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
564 VNFCDict
[vnfc
['name']]["image_id"] = image_id
565 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
568 # Step 7. Storing the VNF descriptor in the repository
569 if "descriptor" not in vnf_descriptor
["vnf"]:
570 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
572 # Step 8. Adding the VNF to the NFVO DB
573 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
575 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
576 _
, message
= rollback(mydb
, vims
, rollback_list
)
577 if isinstance(e
, db_base_Exception
):
578 error_text
= "Exception at database"
579 elif isinstance(e
, KeyError):
580 error_text
= "KeyError exception "
581 e
.http_code
= HTTP_Internal_Server_Error
583 error_text
= "Exception at VIM"
584 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
585 #logger.error("start_scenario %s", error_text)
586 raise NfvoException(error_text
, e
.http_code
)
588 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
591 # Step 1. Check the VNF descriptor
592 check_vnf_descriptor(vnf_descriptor
)
593 # Step 2. Check tenant exist
594 if tenant_id
!= "any":
595 check_tenant(mydb
, tenant_id
)
596 if "tenant_id" in vnf_descriptor
["vnf"]:
597 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
598 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
601 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
602 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
603 vims
= get_vim(mydb
, tenant_id
)
607 # Step 4. Review the descriptor and add missing fields
608 #print vnf_descriptor
609 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
610 vnf_name
= vnf_descriptor
['vnf']['name']
611 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
612 if "physical" in vnf_descriptor
['vnf']:
613 del vnf_descriptor
['vnf']['physical']
614 #print vnf_descriptor
615 # Step 5. Check internal connections
616 # TODO: to be moved to step 1????
617 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
618 for ic
in internal_connections
:
619 if len(ic
['elements'])>2 and ic
['type']=='e-line':
620 raise NfvoException("Mismatch 'type':'e-line' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'e-lan'".format(len(ic
), ic
['name']),
623 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
624 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
625 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
627 #For each VNFC, we add it to the VNFCDict and we create a flavor.
628 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
629 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
631 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
632 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
634 VNFCitem
["name"] = vnfc
['name']
635 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
637 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
640 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
641 myflavorDict
["description"] = VNFCitem
["description"]
642 myflavorDict
["ram"] = vnfc
.get("ram", 0)
643 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
644 myflavorDict
["disk"] = vnfc
.get("disk", 1)
645 myflavorDict
["extended"] = {}
647 devices
= vnfc
.get("devices")
649 myflavorDict
["extended"]["devices"] = devices
652 # 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
653 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
655 # Previous code has been commented
656 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
657 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
658 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
659 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
661 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
663 # print "Error creating flavor: unknown processor model. Rollback successful."
664 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
666 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
667 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
669 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
670 myflavorDict
['extended']['numas'] = vnfc
['numas']
674 # Step 6.2 New flavors are created in the VIM
675 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
677 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
678 VNFCitem
["flavor_id"] = flavor_id
679 VNFCDict
[vnfc
['name']] = VNFCitem
681 logger
.debug("Creating new images in the VIM for each VNFC")
682 # Step 6.3 New images are created in the VIM
683 #For each VNFC, we must create the appropriate image.
684 #This "for" loop might be integrated with the previous one
685 #In case this integration is made, the VNFCDict might become a VNFClist.
686 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
687 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
689 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
690 image_dict
['universal_name']=vnfc
.get('image name')
691 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
692 image_dict
['location']=vnfc
.get('VNFC image')
693 image_dict
['checksum']=vnfc
.get('image checksum')
694 image_metadata_dict
= vnfc
.get('image metadata', None)
695 image_metadata_str
= None
696 if image_metadata_dict
is not None:
697 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
698 image_dict
['metadata']=image_metadata_str
699 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
700 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
701 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
702 VNFCDict
[vnfc
['name']]["image_id"] = image_id
703 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
706 # Step 7. Storing the VNF descriptor in the repository
707 if "descriptor" not in vnf_descriptor
["vnf"]:
708 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
710 # Step 8. Adding the VNF to the NFVO DB
711 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
713 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
714 _
, message
= rollback(mydb
, vims
, rollback_list
)
715 if isinstance(e
, db_base_Exception
):
716 error_text
= "Exception at database"
717 elif isinstance(e
, KeyError):
718 error_text
= "KeyError exception "
719 e
.http_code
= HTTP_Internal_Server_Error
721 error_text
= "Exception at VIM"
722 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
723 #logger.error("start_scenario %s", error_text)
724 raise NfvoException(error_text
, e
.http_code
)
726 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
727 #check valid tenant_id
728 check_tenant(mydb
, tenant_id
)
731 if tenant_id
!= "any":
732 where_or
["tenant_id"] = tenant_id
733 where_or
["public"] = True
734 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
737 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
738 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
739 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
740 data
={'vnf' : filtered_content
}
742 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
743 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description'),
744 WHERE
={'vnfs.uuid': vnf_id
} )
746 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
748 data
['vnf']['VNFC'] = content
749 #TODO: GET all the information from a VNFC and include it in the output.
752 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
753 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
754 WHERE
={'vnfs.uuid': vnf_id
} )
755 data
['vnf']['nets'] = content
757 #GET ip-profile for each net
758 for net
in data
['vnf']['nets']:
759 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
760 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
761 WHERE
={'net_id': net
["uuid"]} )
762 if len(ipprofiles
)==1:
763 net
["ip_profile"] = ipprofiles
[0]
764 elif len(ipprofiles
)>1:
765 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
768 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
770 #GET External Interfaces
771 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
772 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
773 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
774 WHERE
={'vnfs.uuid': vnf_id
},
775 WHERE_NOT
={'interfaces.external_name': None} )
777 data
['vnf']['external-connections'] = content
782 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
784 if tenant_id
!= "any":
785 check_tenant(mydb
, tenant_id
)
786 # Get the URL of the VIM from the nfvo_tenant and the datacenter
787 vims
= get_vim(mydb
, tenant_id
)
791 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
793 if tenant_id
!= "any":
794 where_or
["tenant_id"] = tenant_id
795 where_or
["public"] = True
796 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
799 # "Getting the list of flavors and tenants of the VNF"
800 flavorList
= get_flavorlist(mydb
, vnf_id
)
801 if len(flavorList
)==0:
802 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
804 imageList
= get_imagelist(mydb
, vnf_id
)
805 if len(imageList
)==0:
806 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
808 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
810 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
813 for flavor
in flavorList
:
814 #check if flavor is used by other vnf
816 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
818 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
820 #flavor not used, must be deleted
822 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
824 if flavor_vim
["datacenter_id"] not in vims
:
826 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
828 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
830 myvim
.delete_flavor(flavor_vim
["vim_id"])
831 except vimconn
.vimconnNotFoundException
as e
:
832 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
833 except vimconn
.vimconnException
as e
:
834 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
835 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
836 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
837 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
838 mydb
.delete_row_by_id('flavors', flavor
)
839 except db_base_Exception
as e
:
840 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
841 undeletedItems
.append("flavor %s" % flavor
)
844 for image
in imageList
:
846 #check if image is used by other vnf
847 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
849 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
851 #image not used, must be deleted
853 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
855 if image_vim
["datacenter_id"] not in vims
:
857 if image_vim
['created']=='false': #skip this image because not created by openmano
859 myvim
=vims
[ image_vim
["datacenter_id"] ]
861 myvim
.delete_image(image_vim
["vim_id"])
862 except vimconn
.vimconnNotFoundException
as e
:
863 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
864 except vimconn
.vimconnException
as e
:
865 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
866 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
867 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
868 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
869 mydb
.delete_row_by_id('images', image
)
870 except db_base_Exception
as e
:
871 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
872 undeletedItems
.append("image %s" % image
)
874 return vnf_id
+ " " + vnf
["name"]
876 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
878 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
879 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
883 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
884 myvim
= vims
.values()[0]
885 result
,servers
= myvim
.get_hosts_info()
887 return result
, servers
888 topology
= {'name':myvim
['name'] , 'servers': servers
}
889 return result
, topology
891 def get_hosts(mydb
, nfvo_tenant_id
):
892 vims
= get_vim(mydb
, nfvo_tenant_id
)
894 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
896 #print "nfvo.datacenter_action() error. Several datacenters found"
897 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
898 myvim
= vims
.values()[0]
900 hosts
= myvim
.get_hosts()
901 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
903 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
905 server
={'name':host
['name'], 'vms':[]}
906 for vm
in host
['instances']:
907 #get internal name and model
909 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
910 WHERE
={'vim_vm_id':vm
['id']} )
912 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
914 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
916 except db_base_Exception
as e
:
917 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
918 datacenter
['Datacenters'][0]['servers'].append(server
)
919 #return -400, "en construccion"
921 #print 'datacenters '+ json.dumps(datacenter, indent=4)
923 except vimconn
.vimconnException
as e
:
924 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
926 def new_scenario(mydb
, tenant_id
, topo
):
928 # result, vims = get_vim(mydb, tenant_id)
930 # return result, vims
932 if tenant_id
!= "any":
933 check_tenant(mydb
, tenant_id
)
934 if "tenant_id" in topo
:
935 if topo
["tenant_id"] != tenant_id
:
936 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
941 #1.1: get VNFs and external_networks (other_nets).
943 other_nets
={} #external_networks, bridge_networks and data_networkds
944 nodes
= topo
['topology']['nodes']
945 for k
in nodes
.keys():
946 if nodes
[k
]['type'] == 'VNF':
948 vnfs
[k
]['ifaces'] = {}
949 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
950 other_nets
[k
] = nodes
[k
]
951 other_nets
[k
]['external']=True
952 elif nodes
[k
]['type'] == 'network':
953 other_nets
[k
] = nodes
[k
]
954 other_nets
[k
]['external']=False
957 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
958 for name
,vnf
in vnfs
.items():
960 where_or
={"tenant_id": tenant_id
, 'public': "true"}
962 error_pos
= "'topology':'nodes':'" + name
+ "'"
964 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
965 where
['uuid'] = vnf
['vnf_id']
966 if 'VNF model' in vnf
:
967 error_text
+= " 'VNF model' " + vnf
['VNF model']
968 where
['name'] = vnf
['VNF model']
970 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
972 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
978 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
980 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
981 vnf
['uuid']=vnf_db
[0]['uuid']
982 vnf
['description']=vnf_db
[0]['description']
983 #get external interfaces
984 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
985 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
986 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
987 for ext_iface
in ext_ifaces
:
988 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
990 #1.4 get list of connections
991 conections
= topo
['topology']['connections']
993 conections_list_name
= []
994 for k
in conections
.keys():
995 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
996 ifaces_list
= conections
[k
]['nodes'].items()
997 elif type(conections
[k
]['nodes'])==list: #list with dictionary
999 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1000 for k2
in conection_pair_list
:
1003 con_type
= conections
[k
].get("type", "link")
1004 if con_type
!= "link":
1006 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1007 other_nets
[k
] = {'external': False}
1008 if conections
[k
].get("graph"):
1009 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1010 ifaces_list
.append( (k
, None) )
1013 if con_type
== "external_network":
1014 other_nets
[k
]['external'] = True
1015 if conections
[k
].get("model"):
1016 other_nets
[k
]["model"] = conections
[k
]["model"]
1018 other_nets
[k
]["model"] = k
1019 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1020 other_nets
[k
]["model"] = con_type
1022 conections_list_name
.append(k
)
1023 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)
1024 #print set(ifaces_list)
1025 #check valid VNF and iface names
1026 for iface
in ifaces_list
:
1027 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1028 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1029 str(k
), iface
[0]), HTTP_Not_Found
)
1030 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1031 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1032 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1034 #1.5 unify connections from the pair list to a consolidated list
1036 while index
< len(conections_list
):
1038 while index2
< len(conections_list
):
1039 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1040 conections_list
[index
] |
= conections_list
[index2
]
1041 del conections_list
[index2
]
1042 del conections_list_name
[index2
]
1045 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1047 #for k in conections_list:
1052 #1.6 Delete non external nets
1053 # for k in other_nets.keys():
1054 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1055 # for con in conections_list:
1057 # for index in range(0,len(con)):
1058 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1059 # for index in delete_indexes:
1062 #1.7: Check external_ports are present at database table datacenter_nets
1063 for k
,net
in other_nets
.items():
1064 error_pos
= "'topology':'nodes':'" + k
+ "'"
1065 if net
['external']==False:
1066 if 'name' not in net
:
1068 if 'model' not in net
:
1069 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1070 if net
['model']=='bridge_net':
1071 net
['type']='bridge';
1072 elif net
['model']=='dataplane_net':
1075 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1077 #IF we do not want to check that external network exist at datacenter
1082 # if 'net_id' in net:
1083 # error_text += " 'net_id' " + net['net_id']
1084 # WHERE_['uuid'] = net['net_id']
1085 # if 'model' in net:
1086 # error_text += " 'model' " + net['model']
1087 # WHERE_['name'] = net['model']
1088 # if len(WHERE_) == 0:
1089 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1090 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1091 # FROM='datacenter_nets', WHERE=WHERE_ )
1093 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1095 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1096 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1098 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1099 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1100 # other_nets[k].update(net_db[0])
1103 net_nb
=0 #Number of nets
1104 for con
in conections_list
:
1105 #check if this is connected to a external net
1109 for index
in range(0,len(con
)):
1110 #check if this is connected to a external net
1111 for net_key
in other_nets
.keys():
1112 if con
[index
][0]==net_key
:
1113 if other_net_index
>=0:
1114 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1115 #print "nfvo.new_scenario " + error_text
1116 raise NfvoException(error_text
, HTTP_Bad_Request
)
1118 other_net_index
= index
1119 net_target
= net_key
1121 #print "other_net_index", other_net_index
1123 if other_net_index
>=0:
1124 del con
[other_net_index
]
1125 #IF we do not want to check that external network exist at datacenter
1126 if other_nets
[net_target
]['external'] :
1127 if "name" not in other_nets
[net_target
]:
1128 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1129 if other_nets
[net_target
]["type"] == "external_network":
1130 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1131 other_nets
[net_target
]["type"] = "data"
1133 other_nets
[net_target
]["type"] = "bridge"
1135 # if other_nets[net_target]['external'] :
1136 # 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
1137 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1138 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1139 # print "nfvo.new_scenario " + error_text
1140 # return -HTTP_Bad_Request, error_text
1143 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1146 net_type_bridge
=False
1148 net_target
= "__-__net"+str(net_nb
)
1149 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1150 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1153 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1154 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1155 if iface_type
=='mgmt' or iface_type
=='bridge':
1156 net_type_bridge
= True
1158 net_type_data
= True
1159 if net_type_bridge
and net_type_data
:
1160 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1161 #print "nfvo.new_scenario " + error_text
1162 raise NfvoException(error_text
, HTTP_Bad_Request
)
1163 elif net_type_bridge
:
1166 type_
='data' if len(con
)>2 else 'ptp'
1167 net_list
[net_target
]['type'] = type_
1170 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1171 #print "nfvo.new_scenario " + error_text
1173 raise NfvoException(error_text
, HTTP_Bad_Request
)
1175 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1176 #1.8.1 obtain management net
1177 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1178 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1179 #1.8.2 check all interfaces from all vnfs
1181 add_mgmt_net
= False
1182 for vnf
in vnfs
.values():
1183 for iface
in vnf
['ifaces'].values():
1184 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1185 #iface not connected
1186 iface
['net_key'] = 'mgmt'
1188 if add_mgmt_net
and 'mgmt' not in net_list
:
1189 net_list
['mgmt']=mgmt_net
[0]
1190 net_list
['mgmt']['external']=True
1191 net_list
['mgmt']['graph']={'visible':False}
1193 net_list
.update(other_nets
)
1195 #print 'net_list', net_list
1200 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1201 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1202 'tenant_id':tenant_id
, 'name':topo
['name'],
1203 'description':topo
.get('description',topo
['name']),
1204 'public': topo
.get('public', False)
1209 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
):
1210 scenario
= scenario_dict
["scenario"]
1211 if tenant_id
!= "any":
1212 check_tenant(mydb
, tenant_id
)
1213 if "tenant_id" in scenario
:
1214 if scenario
["tenant_id"] != tenant_id
:
1215 print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1216 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1217 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1221 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1222 for name
,vnf
in scenario
["vnfs"].iteritems():
1224 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1226 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1228 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1229 where
['uuid'] = vnf
['vnf_id']
1230 if 'vnf_name' in vnf
:
1231 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1232 where
['name'] = vnf
['vnf_name']
1234 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1235 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1241 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1243 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1244 vnf
['uuid']=vnf_db
[0]['uuid']
1245 vnf
['description']=vnf_db
[0]['description']
1247 #get external interfaces
1248 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1249 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1250 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1251 for ext_iface
in ext_ifaces
:
1252 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1254 #2: Insert net_key at every vnf interface
1255 for net_name
,net
in scenario
["networks"].iteritems():
1256 net_type_bridge
=False
1258 for iface_dict
in net
["interfaces"]:
1259 for vnf
,iface
in iface_dict
.iteritems():
1260 if vnf
not in scenario
["vnfs"]:
1261 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1262 #print "nfvo.new_scenario_v02 " + error_text
1263 raise NfvoException(error_text
, HTTP_Not_Found
)
1264 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1265 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1266 #print "nfvo.new_scenario_v02 " + error_text
1267 raise NfvoException(error_text
, HTTP_Bad_Request
)
1268 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1269 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1270 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1271 #print "nfvo.new_scenario_v02 " + error_text
1272 raise NfvoException(error_text
, HTTP_Bad_Request
)
1273 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1274 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1275 if iface_type
=='mgmt' or iface_type
=='bridge':
1276 net_type_bridge
= True
1278 net_type_data
= True
1279 if net_type_bridge
and net_type_data
:
1280 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1281 #print "nfvo.new_scenario " + error_text
1282 raise NfvoException(error_text
, HTTP_Bad_Request
)
1283 elif net_type_bridge
:
1286 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1288 net
['name'] = net_name
1289 net
['external'] = net
.get('external', False)
1291 #3: insert at database
1292 scenario
["nets"] = scenario
["networks"]
1293 scenario
['tenant_id'] = tenant_id
1294 scenario_id
= mydb
.new_scenario( scenario
)
1297 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1298 data
["uuid"] = scenario_id
1299 data
["tenant_id"] = tenant_id
1300 c
= mydb
.edit_scenario( data
)
1303 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1304 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1305 datacenter_id
= None
1306 datacenter_name
=None
1307 if datacenter
!= None:
1308 if utils
.check_valid_uuid(datacenter
):
1309 datacenter_id
= datacenter
1311 datacenter_name
= datacenter
1312 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
)
1314 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
1316 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
1317 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1318 myvim
= vims
.values()[0]
1319 myvim_tenant
= myvim
['tenant_id']
1320 datacenter_id
= myvim
['id']
1321 datacenter_name
= myvim
['name']
1322 datacenter_tenant_id
= myvim
['config']['datacenter_tenant_id']
1325 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1326 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1327 scenarioDict
['datacenter_tenant_id'] = datacenter_tenant_id
1328 scenarioDict
['datacenter_id'] = datacenter_id
1329 #print '================scenarioDict======================='
1330 #print json.dumps(scenarioDict, indent=4)
1331 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1333 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1334 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1336 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1337 auxNetDict
['scenario'] = {}
1339 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1340 for sce_net
in scenarioDict
['nets']:
1341 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1343 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1344 myNetName
= myNetName
[0:255] #limit length
1345 myNetType
= sce_net
['type']
1347 myNetDict
["name"] = myNetName
1348 myNetDict
["type"] = myNetType
1349 myNetDict
["tenant_id"] = myvim_tenant
1350 myNetIPProfile
= sce_net
.get('ip_profile', None)
1352 #We should use the dictionary as input parameter for new_network
1354 if not sce_net
["external"]:
1355 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1356 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1357 sce_net
['vim_id'] = network_id
1358 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1359 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1360 sce_net
["created"] = True
1362 if sce_net
['vim_id'] == None:
1363 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1364 _
, message
= rollback(mydb
, vims
, rollbackList
)
1365 logger
.error("nfvo.start_scenario: %s", error_text
)
1366 raise NfvoException(error_text
, HTTP_Bad_Request
)
1367 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1368 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1370 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1371 #For each vnf net, we create it and we add it to instanceNetlist.
1372 for sce_vnf
in scenarioDict
['vnfs']:
1373 for net
in sce_vnf
['nets']:
1374 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1376 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1377 myNetName
= myNetName
[0:255] #limit length
1378 myNetType
= net
['type']
1380 myNetDict
["name"] = myNetName
1381 myNetDict
["type"] = myNetType
1382 myNetDict
["tenant_id"] = myvim_tenant
1383 myNetIPProfile
= net
.get('ip_profile', None)
1386 #We should use the dictionary as input parameter for new_network
1387 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1388 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1389 net
['vim_id'] = network_id
1390 if sce_vnf
['uuid'] not in auxNetDict
:
1391 auxNetDict
[sce_vnf
['uuid']] = {}
1392 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1393 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1394 net
["created"] = True
1396 #print "auxNetDict:"
1397 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1399 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1400 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1402 for sce_vnf
in scenarioDict
['vnfs']:
1403 for vm
in sce_vnf
['vms']:
1406 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1407 myVMDict
['name'] = "%s.%s.%d" % (instance_scenario_name
,sce_vnf
['name'],i
)
1408 #myVMDict['description'] = vm['description']
1409 myVMDict
['description'] = myVMDict
['name'][0:99]
1411 myVMDict
['start'] = "no"
1412 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1413 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1415 #create image at vim in case it not exist
1416 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1417 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1418 vm
['vim_image_id'] = image_id
1420 #create flavor at vim in case it not exist
1421 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1422 if flavor_dict
['extended']!=None:
1423 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1424 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1425 vm
['vim_flavor_id'] = flavor_id
1428 myVMDict
['imageRef'] = vm
['vim_image_id']
1429 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1430 myVMDict
['networks'] = []
1431 for iface
in vm
['interfaces']:
1433 if iface
['type']=="data":
1434 netDict
['type'] = iface
['model']
1435 elif "model" in iface
and iface
["model"]!=None:
1436 netDict
['model']=iface
['model']
1437 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1438 #discover type of interface looking at flavor
1439 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1440 for flavor_iface
in numa
.get('interfaces',[]):
1441 if flavor_iface
.get('name') == iface
['internal_name']:
1442 if flavor_iface
['dedicated'] == 'yes':
1443 netDict
['type']="PF" #passthrough
1444 elif flavor_iface
['dedicated'] == 'no':
1445 netDict
['type']="VF" #siov
1446 elif flavor_iface
['dedicated'] == 'yes:sriov':
1447 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1448 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1450 netDict
["use"]=iface
['type']
1451 if netDict
["use"]=="data" and not netDict
.get("type"):
1452 #print "netDict", netDict
1453 #print "iface", iface
1454 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'])
1455 if flavor_dict
.get('extended')==None:
1456 raise NfvoException(e_text
+ "After database migration some information is not available. \
1457 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1459 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1460 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1461 netDict
["type"]="virtual"
1462 if "vpci" in iface
and iface
["vpci"] is not None:
1463 netDict
['vpci'] = iface
['vpci']
1464 if "mac" in iface
and iface
["mac"] is not None:
1465 netDict
['mac_address'] = iface
['mac']
1466 netDict
['name'] = iface
['internal_name']
1467 if iface
['net_id'] is None:
1468 for vnf_iface
in sce_vnf
["interfaces"]:
1471 if vnf_iface
['interface_id']==iface
['uuid']:
1472 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1475 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1476 #skip bridge ifaces not connected to any net
1477 #if 'net_id' not in netDict or netDict['net_id']==None:
1479 myVMDict
['networks'].append(netDict
)
1480 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1481 #print myVMDict['name']
1482 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1483 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1484 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1485 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1486 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1487 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1488 vm
['vim_id'] = vm_id
1489 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1490 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1491 for net
in myVMDict
['networks']:
1493 for iface
in vm
['interfaces']:
1494 if net
["name"]==iface
["internal_name"]:
1495 iface
["vim_id"]=net
["vim_id"]
1498 logger
.debug("start scenario Deployment done")
1499 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1500 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1501 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1502 return mydb
.get_instance_scenario(instance_id
)
1504 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1505 _
, message
= rollback(mydb
, vims
, rollbackList
)
1506 if isinstance(e
, db_base_Exception
):
1507 error_text
= "Exception at database"
1509 error_text
= "Exception at VIM"
1510 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1511 #logger.error("start_scenario %s", error_text)
1512 raise NfvoException(error_text
, e
.http_code
)
1514 def unify_cloud_config(cloud_config
):
1515 index_to_delete
= []
1516 users
= cloud_config
.get("users", [])
1517 for index0
in range(0,len(users
)):
1518 if index0
in index_to_delete
:
1520 for index1
in range(index0
+1,len(users
)):
1521 if index1
in index_to_delete
:
1523 if users
[index0
]["name"] == users
[index1
]["name"]:
1524 index_to_delete
.append(index1
)
1525 for key
in users
[index1
].get("key-pairs",()):
1526 if "key-pairs" not in users
[index0
]:
1527 users
[index0
]["key-pairs"] = [key
]
1528 elif key
not in users
[index0
]["key-pairs"]:
1529 users
[index0
]["key-pairs"].append(key
)
1530 index_to_delete
.sort(reverse
=True)
1531 for index
in index_to_delete
:
1534 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None):
1535 datacenter_id
= None
1536 datacenter_name
= None
1537 if datacenter_id_name
:
1538 if utils
.check_valid_uuid(datacenter_id_name
):
1539 datacenter_id
= datacenter_id_name
1541 datacenter_name
= datacenter_id_name
1542 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
=None)
1544 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1546 #print "nfvo.datacenter_action() error. Several datacenters found"
1547 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1548 return vims
.keys()[0], vims
.values()[0]
1550 def new_scenario_v03(mydb
, tenant_id
, scenario_dict
):
1551 scenario
= scenario_dict
["scenario"]
1552 if tenant_id
!= "any":
1553 check_tenant(mydb
, tenant_id
)
1554 if "tenant_id" in scenario
:
1555 if scenario
["tenant_id"] != tenant_id
:
1556 logger("Tenant '%s' not found", tenant_id
)
1557 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1558 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1562 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1563 for name
,vnf
in scenario
["vnfs"].iteritems():
1565 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1567 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1569 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1570 where
['uuid'] = vnf
['vnf_id']
1571 if 'vnf_name' in vnf
:
1572 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1573 where
['name'] = vnf
['vnf_name']
1575 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1576 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1582 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1584 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1585 vnf
['uuid']=vnf_db
[0]['uuid']
1586 vnf
['description']=vnf_db
[0]['description']
1588 # get external interfaces
1589 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1590 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1591 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1592 for ext_iface
in ext_ifaces
:
1593 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1595 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1597 #2: Insert net_key and ip_address at every vnf interface
1598 for net_name
,net
in scenario
["networks"].iteritems():
1599 net_type_bridge
=False
1601 for iface_dict
in net
["interfaces"]:
1602 logger
.debug("Iface_dict %s", iface_dict
)
1603 vnf
= iface_dict
["vnf"]
1604 iface
= iface_dict
["vnf_interface"]
1605 if vnf
not in scenario
["vnfs"]:
1606 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1607 #logger.debug(error_text)
1608 raise NfvoException(error_text
, HTTP_Not_Found
)
1609 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1610 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1611 #logger.debug(error_text)
1612 raise NfvoException(error_text
, HTTP_Bad_Request
)
1613 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1614 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1615 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1616 #logger.debug(error_text)
1617 raise NfvoException(error_text
, HTTP_Bad_Request
)
1618 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1619 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['ip_address'] = iface_dict
.get('ip_address',None)
1620 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1621 if iface_type
=='mgmt' or iface_type
=='bridge':
1622 net_type_bridge
= True
1624 net_type_data
= True
1625 if net_type_bridge
and net_type_data
:
1626 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1627 #logger.debug(error_text)
1628 raise NfvoException(error_text
, HTTP_Bad_Request
)
1629 elif net_type_bridge
:
1632 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1634 if ("implementation" in net
):
1635 if (type_
== "bridge" and net
["implementation"] == "underlay"):
1636 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at 'network':'%s'" % (net_name
)
1637 #logger.debug(error_text)
1638 raise NfvoException(error_text
, HTTP_Bad_Request
)
1639 elif (type_
<> "bridge" and net
["implementation"] == "overlay"):
1640 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at 'network':'%s'" % (net_name
)
1641 #logger.debug(error_text)
1642 raise NfvoException(error_text
, HTTP_Bad_Request
)
1643 net
.pop("implementation")
1645 if (type_
== "data" and net
["type"] == "e-line"):
1646 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type 'e-line' at 'network':'%s'" % (net_name
)
1647 #logger.debug(error_text)
1648 raise NfvoException(error_text
, HTTP_Bad_Request
)
1649 elif (type_
== "ptp" and net
["type"] == "e-lan"):
1653 net
['name'] = net_name
1654 net
['external'] = net
.get('external', False)
1656 #3: insert at database
1657 scenario
["nets"] = scenario
["networks"]
1658 scenario
['tenant_id'] = tenant_id
1659 scenario_id
= mydb
.new_scenario2(scenario
)
1663 '''Takes dict d and updates it with the values in dict u.'''
1664 '''It merges all depth levels'''
1665 for k
, v
in u
.iteritems():
1666 if isinstance(v
, collections
.Mapping
):
1667 r
= update(d
.get(k
, {}), v
)
1673 def create_instance(mydb
, tenant_id
, instance_dict
):
1674 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1675 #logger.debug("Creating instance...")
1676 scenario
= instance_dict
["scenario"]
1678 #find main datacenter
1680 datacenter
= instance_dict
.get("datacenter")
1681 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1682 myvims
[default_datacenter_id
] = vim
1683 #myvim_tenant = myvim['tenant_id']
1684 # default_datacenter_name = vim['name']
1685 default_datacenter_tenant_id
= vim
['config']['datacenter_tenant_id'] #TODO review
1688 #print "Checking that the scenario exists and getting the scenario dictionary"
1689 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1691 #logger.debug("Dictionaries before merging")
1692 #logger.debug("InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1693 #logger.debug("ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1695 scenarioDict
['datacenter_tenant_id'] = default_datacenter_tenant_id
1696 scenarioDict
['datacenter_id'] = default_datacenter_id
1698 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1699 auxNetDict
['scenario'] = {}
1701 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1702 instance_name
= instance_dict
["name"]
1703 instance_description
= instance_dict
.get("description")
1705 #0 check correct parameters
1706 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1708 for scenario_net
in scenarioDict
['nets']:
1709 if net_name
== scenario_net
["name"]:
1713 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1714 if "sites" not in net_instance_desc
:
1715 net_instance_desc
["sites"] = [ {} ]
1716 site_without_datacenter_field
= False
1717 for site
in net_instance_desc
["sites"]:
1718 if site
.get("datacenter"):
1719 if site
["datacenter"] not in myvims
:
1720 #Add this datacenter to myvims
1721 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1723 site
["datacenter"] = d
#change name to id
1725 if site_without_datacenter_field
:
1726 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1727 site_without_datacenter_field
= True
1728 site
["datacenter"] = default_datacenter_id
#change name to id
1730 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
1732 for scenario_vnf
in scenarioDict
['vnfs']:
1733 if vnf_name
== scenario_vnf
['name']:
1737 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
1738 if "datacenter" in vnf_instance_desc
:
1739 #Add this datacenter to myvims
1740 if vnf_instance_desc
["datacenter"] not in myvims
:
1741 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
1743 scenario_vnf
["datacenter"] = d
#change name to id
1744 #0.1 parse cloud-config parameters
1745 cloud_config
= scenarioDict
.get("cloud-config", {})
1746 if instance_dict
.get("cloud-config"):
1747 cloud_config
.update( instance_dict
["cloud-config"])
1748 if not cloud_config
:
1751 scenarioDict
["cloud-config"] = cloud_config
1752 unify_cloud_config(cloud_config
)
1754 #0.2 merge instance information into scenario
1755 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
1756 #However, this is not possible yet.
1757 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1758 for scenario_net
in scenarioDict
['nets']:
1759 if net_name
== scenario_net
["name"]:
1760 if 'ip-profile' in net_instance_desc
:
1761 ipprofile
= net_instance_desc
['ip-profile']
1762 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
1763 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
1764 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
1765 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
1766 if 'dhcp' in ipprofile
:
1767 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
1768 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
1769 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
1770 del ipprofile
['dhcp']
1771 update(scenario_net
['ip_profile'],ipprofile
)
1772 for interface
in net_instance_desc
.get('interfaces', () ):
1773 if 'ip_address' in interface
:
1774 for vnf
in scenarioDict
['vnfs']:
1775 if interface
['vnf'] == vnf
['name']:
1776 for vnf_interface
in vnf
['interfaces']:
1777 if interface
['vnf_interface'] == vnf_interface
['external_name']:
1778 vnf_interface
['ip_address']=interface
['ip_address']
1780 #logger.debug("Merged dictionary")
1781 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
1784 #1. Creating new nets (sce_nets) in the VIM"
1785 for sce_net
in scenarioDict
['nets']:
1786 sce_net
["vim_id_sites"]={}
1787 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
1788 net_name
= descriptor_net
.get("vim-network-name")
1789 auxNetDict
['scenario'][sce_net
['uuid']] = {}
1791 sites
= descriptor_net
.get("sites", [ {} ])
1793 if site
.get("datacenter"):
1794 vim
= myvims
[ site
["datacenter"] ]
1795 datacenter_id
= site
["datacenter"]
1797 vim
= myvims
[ default_datacenter_id
]
1798 datacenter_id
= default_datacenter_id
1800 net_type
= sce_net
['type']
1801 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
1802 if sce_net
["external"]:
1804 net_name
= sce_net
["name"]
1805 if "netmap-use" in site
or "netmap-create" in site
:
1806 create_network
= False
1807 lookfor_network
= False
1808 if "netmap-use" in site
:
1809 lookfor_network
= True
1810 if utils
.check_valid_uuid(site
["netmap-use"]):
1811 filter_text
= "scenario id '%s'" % site
["netmap-use"]
1812 lookfor_filter
["id"] = site
["netmap-use"]
1814 filter_text
= "scenario name '%s'" % site
["netmap-use"]
1815 lookfor_filter
["name"] = site
["netmap-use"]
1816 if "netmap-create" in site
:
1817 create_network
= True
1818 net_vim_name
= net_name
1819 if site
["netmap-create"]:
1820 net_vim_name
= site
["netmap-create"]
1822 elif sce_net
['vim_id'] != None:
1823 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
1824 create_network
= False
1825 lookfor_network
= True
1826 lookfor_filter
["id"] = sce_net
['vim_id']
1827 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
1828 #look for network at datacenter and return error
1830 #There is not a netmap, look at datacenter for a net with this name and create if not found
1831 create_network
= True
1832 lookfor_network
= True
1833 lookfor_filter
["name"] = sce_net
["name"]
1834 net_vim_name
= sce_net
["name"]
1835 filter_text
= "scenario name '%s'" % sce_net
["name"]
1838 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
1839 net_name
= net_name
[:255] #limit length
1840 net_vim_name
= net_name
1841 create_network
= True
1842 lookfor_network
= False
1845 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
1846 if len(vim_nets
) > 1:
1847 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1848 elif len(vim_nets
) == 0:
1849 if not create_network
:
1850 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1852 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
1854 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
1855 create_network
= False
1857 #if network is not external
1858 network_id
= vim
.new_network(net_vim_name
, net_type
, sce_net
.get('ip_profile',None))
1859 sce_net
["vim_id_sites"][datacenter_id
] = network_id
1860 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = network_id
1861 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':network_id
})
1862 sce_net
["created"] = True
1864 #2. Creating new nets (vnf internal nets) in the VIM"
1865 #For each vnf net, we create it and we add it to instanceNetlist.
1866 for sce_vnf
in scenarioDict
['vnfs']:
1867 for net
in sce_vnf
['nets']:
1868 if sce_vnf
.get("datacenter"):
1869 vim
= myvims
[ sce_vnf
["datacenter"] ]
1870 datacenter_id
= sce_vnf
["datacenter"]
1872 vim
= myvims
[ default_datacenter_id
]
1873 datacenter_id
= default_datacenter_id
1874 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
1875 net_name
= descriptor_net
.get("name")
1877 net_name
= "%s.%s" %(instance_name
, net
["name"])
1878 net_name
= net_name
[:255] #limit length
1879 net_type
= net
['type']
1880 network_id
= vim
.new_network(net_name
, net_type
, net
.get('ip_profile',None))
1881 net
['vim_id'] = network_id
1882 if sce_vnf
['uuid'] not in auxNetDict
:
1883 auxNetDict
[sce_vnf
['uuid']] = {}
1884 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1885 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1886 net
["created"] = True
1889 #print "auxNetDict:"
1890 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1892 #3. Creating new vm instances in the VIM
1893 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1894 for sce_vnf
in scenarioDict
['vnfs']:
1895 if sce_vnf
.get("datacenter"):
1896 vim
= myvims
[ sce_vnf
["datacenter"] ]
1897 datacenter_id
= sce_vnf
["datacenter"]
1899 vim
= myvims
[ default_datacenter_id
]
1900 datacenter_id
= default_datacenter_id
1901 sce_vnf
["datacenter_id"] = datacenter_id
1902 sce_vnf
["datacenter_tenant_id"] = vim
['config']['datacenter_tenant_id']
1904 for vm
in sce_vnf
['vms']:
1907 myVMDict
['name'] = "%s.%s.%d" % (instance_name
,sce_vnf
['name'],i
)
1908 myVMDict
['description'] = myVMDict
['name'][0:99]
1910 # myVMDict['start'] = "no"
1911 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1912 #create image at vim in case it not exist
1913 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1914 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
1915 vm
['vim_image_id'] = image_id
1917 #create flavor at vim in case it not exist
1918 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1919 if flavor_dict
['extended']!=None:
1920 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1921 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
1922 vm
['vim_flavor_id'] = flavor_id
1924 myVMDict
['imageRef'] = vm
['vim_image_id']
1925 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1926 myVMDict
['networks'] = []
1927 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
1928 for iface
in vm
['interfaces']:
1930 if iface
['type']=="data":
1931 netDict
['type'] = iface
['model']
1932 elif "model" in iface
and iface
["model"]!=None:
1933 netDict
['model']=iface
['model']
1934 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1935 #discover type of interface looking at flavor
1936 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1937 for flavor_iface
in numa
.get('interfaces',[]):
1938 if flavor_iface
.get('name') == iface
['internal_name']:
1939 if flavor_iface
['dedicated'] == 'yes':
1940 netDict
['type']="PF" #passthrough
1941 elif flavor_iface
['dedicated'] == 'no':
1942 netDict
['type']="VF" #siov
1943 elif flavor_iface
['dedicated'] == 'yes:sriov':
1944 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1945 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1947 netDict
["use"]=iface
['type']
1948 if netDict
["use"]=="data" and not netDict
.get("type"):
1949 #print "netDict", netDict
1950 #print "iface", iface
1951 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'])
1952 if flavor_dict
.get('extended')==None:
1953 raise NfvoException(e_text
+ "After database migration some information is not available. \
1954 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1956 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1957 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1958 netDict
["type"]="virtual"
1959 if "vpci" in iface
and iface
["vpci"] is not None:
1960 netDict
['vpci'] = iface
['vpci']
1961 if "mac" in iface
and iface
["mac"] is not None:
1962 netDict
['mac_address'] = iface
['mac']
1963 netDict
['name'] = iface
['internal_name']
1964 if iface
['net_id'] is None:
1965 for vnf_iface
in sce_vnf
["interfaces"]:
1968 if vnf_iface
['interface_id']==iface
['uuid']:
1969 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
1972 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1973 #skip bridge ifaces not connected to any net
1974 #if 'net_id' not in netDict or netDict['net_id']==None:
1976 myVMDict
['networks'].append(netDict
)
1977 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1978 #print myVMDict['name']
1979 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1980 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1981 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1982 vm_id
= vim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1983 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'], cloud_config
= cloud_config
)
1984 vm
['vim_id'] = vm_id
1985 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1986 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1987 for net
in myVMDict
['networks']:
1989 for iface
in vm
['interfaces']:
1990 if net
["name"]==iface
["internal_name"]:
1991 iface
["vim_id"]=net
["vim_id"]
1993 logger
.debug("create_instance Deployment done")
1994 print yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)
1995 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1996 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
1997 return mydb
.get_instance_scenario(instance_id
)
1998 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
1999 message
= rollback(mydb
, myvims
, rollbackList
)
2000 if isinstance(e
, db_base_Exception
):
2001 error_text
= "database Exception"
2002 elif isinstance(e
, vimconn
.vimconnException
):
2003 error_text
= "VIM Exception"
2005 error_text
= "Exception"
2006 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2007 #logger.error("create_instance: %s", error_text)
2008 raise NfvoException(error_text
, e
.http_code
)
2010 def delete_instance(mydb
, tenant_id
, instance_id
):
2011 #print "Checking that the instance_id exists and getting the instance dictionary"
2012 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2013 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2014 tenant_id
= instanceDict
["tenant_id"]
2015 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2017 vims
= get_vim(mydb
, tenant_id
, instanceDict
['datacenter_id'])
2019 logger
.error("!!!!!! nfvo.delete_instance() datacenter not found!!!!")
2022 myvim
= vims
.values()[0]
2023 except NfvoException
as e
:
2024 logger
.error("!!!!!! nfvo.delete_instance() datacenter Exception!!!! " + str(e
))
2028 #1. Delete from Database
2030 #result,c = mydb.delete_row_by_id('instance_scenarios', instance_id, nfvo_tenant)
2031 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2035 error_msg
= "Not possible to delete VIM VMs and networks. Datacenter not found at database!!!"
2041 for sce_vnf
in instanceDict
['vnfs']:
2044 for vm
in sce_vnf
['vms']:
2046 myvim
.delete_vminstance(vm
['vim_vm_id'])
2047 except vimconn
.vimconnNotFoundException
as e
:
2048 error_msg
+="\n VM id={} not found at VIM".format(vm
['vim_vm_id'])
2049 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2050 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2051 except vimconn
.vimconnException
as e
:
2052 error_msg
+="\n Error: " + e
.http_code
+ " VM id=" + vm
['vim_vm_id']
2053 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s': %s",
2054 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2058 for net
in instanceDict
['nets']:
2059 if not net
['created']:
2060 continue #skip not created nets
2064 myvim
.delete_network(net
['vim_net_id'])
2065 except vimconn
.vimconnNotFoundException
as e
:
2066 error_msg
+="\n NET id={} not found at VIM".format(net
['vim_net_id'])
2067 logger
.warn("NET '%s', VIM id '%s', from VNF_id '%s' not found",
2068 net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'])
2069 except vimconn
.vimconnException
as e
:
2070 error_msg
+="\n Error: " + e
.http_code
+ " Net id=" + net
['vim_vm_id']
2071 logger
.error("Error %d deleting NET '%s', VIM id '%s', from VNF_id '%s': %s",
2072 e
.http_code
, net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'], str(e
))
2073 if len(error_msg
)>0:
2074 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2076 return 'instance ' + message
+ ' deleted'
2078 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2079 '''Refreshes a scenario instance. It modifies instanceDict'''
2081 - 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
2084 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2085 #print "nfvo.refresh_instance begins"
2086 #print json.dumps(instanceDict, indent=4)
2088 #print "Getting the VIM URL and the VIM tenant_id"
2089 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2091 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2092 myvim
= vims
.values()[0]
2094 # 1. Getting VIM vm and net list
2095 vms_updated
= [] #List of VM instance uuids in openmano that were updated
2098 for sce_vnf
in instanceDict
['vnfs']:
2099 for vm
in sce_vnf
['vms']:
2100 vm_list
.append(vm
['vim_vm_id'])
2101 vms_notupdated
.append(vm
["uuid"])
2103 nets_updated
= [] #List of VM instance uuids in openmano that were updated
2106 for net
in instanceDict
['nets']:
2107 net_list
.append(net
['vim_net_id'])
2108 nets_notupdated
.append(net
["uuid"])
2111 # 1. Getting the status of all VMs
2112 vm_dict
= myvim
.refresh_vms_status(vm_list
)
2114 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2115 for sce_vnf
in instanceDict
['vnfs']:
2116 for vm
in sce_vnf
['vms']:
2117 vm_id
= vm
['vim_vm_id']
2118 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
2119 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2120 has_mgmt_iface
= False
2121 for iface
in vm
["interfaces"]:
2122 if iface
["type"]=="mgmt":
2123 has_mgmt_iface
= True
2124 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
2125 vm_dict
[vm_id
]['status'] = "ACTIVE"
2126 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'):
2127 vm
['status'] = vm_dict
[vm_id
]['status']
2128 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
2129 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
2130 # 2.1. Update in openmano DB the VMs whose status changed
2132 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
2133 vms_notupdated
.remove(vm
["uuid"])
2135 vms_updated
.append(vm
["uuid"])
2136 except db_base_Exception
as e
:
2137 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2138 # 2.2. Update in openmano DB the interface VMs
2139 for interface
in interfaces
:
2140 #translate from vim_net_id to instance_net_id
2142 for net
in instanceDict
['nets']:
2143 if net
["vim_net_id"] == interface
["vim_net_id"]:
2144 network_id_list
.append(net
["uuid"])
2145 if not network_id_list
:
2147 del interface
["vim_net_id"]
2149 for network_id
in network_id_list
:
2150 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
2151 except db_base_Exception
as e
:
2152 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
2154 # 3. Getting the status of all nets
2155 net_dict
= myvim
.refresh_nets_status(net_list
)
2157 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2158 # TODO: update nets inside a vnf
2159 for net
in instanceDict
['nets']:
2160 net_id
= net
['vim_net_id']
2161 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'):
2162 net
['status'] = net_dict
[net_id
]['status']
2163 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
2164 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
2165 # 5.1. Update in openmano DB the nets whose status changed
2167 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
2168 nets_notupdated
.remove(net
["uuid"])
2170 nets_updated
.append(net
["uuid"])
2171 except db_base_Exception
as e
:
2172 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2173 except vimconn
.vimconnException
as e
:
2174 #logger.error("VIM exception %s %s", type(e).__name__, str(e))
2175 raise NfvoException(str(e
), e
.http_code
)
2177 # Returns appropriate output
2178 #print "nfvo.refresh_instance finishes"
2179 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2180 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
2181 instance_id
= instanceDict
['uuid']
2182 if len(vms_notupdated
)+len(nets_notupdated
)>0:
2183 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
2184 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
2186 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2188 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2189 #print "Checking that the instance_id exists and getting the instance dictionary"
2190 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2191 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2193 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2194 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2196 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2197 myvim
= vims
.values()[0]
2200 input_vnfs
= action_dict
.pop("vnfs", [])
2201 input_vms
= action_dict
.pop("vms", [])
2202 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2206 for sce_vnf
in instanceDict
['vnfs']:
2207 for vm
in sce_vnf
['vms']:
2208 if not action_over_all
:
2209 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2210 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2213 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2214 if "console" in action_dict
:
2215 if not global_config
["http_console_proxy"]:
2216 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2217 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2218 protocol
=data
["protocol"],
2219 ip
= data
["server"],
2220 port
= data
["port"],
2221 suffix
= data
["suffix"]),
2225 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2226 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2227 "description": "this console is only reachable by local interface",
2232 #print "console data", data
2234 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2235 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2236 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2237 protocol
=data
["protocol"],
2238 ip
= global_config
["http_console_host"],
2239 port
= console_thread
.port
,
2240 suffix
= data
["suffix"]),
2244 except NfvoException
as e
:
2245 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2249 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2251 except vimconn
.vimconnException
as e
:
2252 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2255 if vm_ok
==0: #all goes wrong
2260 def create_or_use_console_proxy_thread(console_server
, console_port
):
2261 #look for a non-used port
2262 console_thread_key
= console_server
+ ":" + str(console_port
)
2263 if console_thread_key
in global_config
["console_thread"]:
2264 #global_config["console_thread"][console_thread_key].start_timeout()
2265 return global_config
["console_thread"][console_thread_key
]
2267 for port
in global_config
["console_port_iterator"]():
2268 #print "create_or_use_console_proxy_thread() port:", port
2269 if port
in global_config
["console_ports"]:
2272 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2274 global_config
["console_thread"][console_thread_key
] = clithread
2275 global_config
["console_ports"][port
] = console_thread_key
2277 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2278 #port used, try with onoher
2280 except cli
.ConsoleProxyException
as e
:
2281 raise NfvoException(str(e
), HTTP_Bad_Request
)
2282 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2284 def check_tenant(mydb
, tenant_id
):
2285 '''check that tenant exists at database'''
2286 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2288 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2291 def new_tenant(mydb
, tenant_dict
):
2292 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2295 def delete_tenant(mydb
, tenant
):
2296 #get nfvo_tenant info
2298 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2299 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2300 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2302 def new_datacenter(mydb
, datacenter_descriptor
):
2303 if "config" in datacenter_descriptor
:
2304 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2305 #Check that datacenter-type is correct
2306 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2309 module
= "vimconn_" + datacenter_type
2310 module_info
= imp
.find_module(module
)
2311 except (IOError, ImportError):
2312 if module_info
and module_info
[0]:
2313 file.close(module_info
[0])
2314 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2316 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2317 return datacenter_id
2319 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2320 #obtain data, check that only one exist
2321 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2323 datacenter_id
= datacenter
['uuid']
2324 where
={'uuid': datacenter
['uuid']}
2325 if "config" in datacenter_descriptor
:
2326 if datacenter_descriptor
['config']!=None:
2328 new_config_dict
= datacenter_descriptor
["config"]
2331 for k
in new_config_dict
:
2332 if new_config_dict
[k
]==None:
2335 config_dict
= yaml
.load(datacenter
["config"])
2336 config_dict
.update(new_config_dict
)
2340 except Exception as e
:
2341 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2342 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2343 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2344 return datacenter_id
2346 def delete_datacenter(mydb
, datacenter
):
2347 #get nfvo_tenant info
2348 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2349 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2350 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2352 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None):
2353 #get datacenter info
2354 if utils
.check_valid_uuid(datacenter
):
2355 vims
= get_vim(mydb
, datacenter_id
=datacenter
, vim_tenant_name
=vim_tenant_name
, vim_user
=vim_username
, vim_passwd
=vim_password
)
2357 vims
= get_vim(mydb
, datacenter_name
=datacenter
, vim_tenant_name
=vim_tenant_name
, vim_user
=vim_username
, vim_passwd
=vim_password
)
2359 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2361 #print "nfvo.datacenter_action() error. Several datacenters found"
2362 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2364 datacenter_id
=vims
.keys()[0]
2365 myvim
=vims
[datacenter_id
]
2366 datacenter_name
=myvim
["name"]
2368 create_vim_tenant
=True if vim_tenant_id
==None and vim_tenant_name
==None else False
2370 #get nfvo_tenant info
2371 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2372 if vim_tenant_name
==None:
2373 vim_tenant_name
=tenant_dict
['name']
2375 #check that this association does not exist before
2376 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2377 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2378 if len(tenants_datacenters
)>0:
2379 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2381 vim_tenant_id_exist_atdb
=False
2382 if not create_vim_tenant
:
2383 where_
={"datacenter_id": datacenter_id
}
2384 if vim_tenant_id
!=None:
2385 where_
["vim_tenant_id"] = vim_tenant_id
2386 if vim_tenant_name
!=None:
2387 where_
["vim_tenant_name"] = vim_tenant_name
2388 #check if vim_tenant_id is already at database
2389 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2390 if len(datacenter_tenants_dict
)>=1:
2391 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2392 vim_tenant_id_exist_atdb
=True
2393 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2395 datacenter_tenants_dict
= {}
2396 #insert at table datacenter_tenants
2397 else: #if vim_tenant_id==None:
2398 #create tenant at VIM if not provided
2400 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2401 except vimconn
.vimconnException
as e
:
2402 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2403 datacenter_tenants_dict
= {}
2404 datacenter_tenants_dict
["created"]="true"
2406 #fill datacenter_tenants table
2407 if not vim_tenant_id_exist_atdb
:
2408 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2409 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2410 datacenter_tenants_dict
["user"] = vim_username
2411 datacenter_tenants_dict
["passwd"] = vim_password
2412 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2413 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2414 datacenter_tenants_dict
["uuid"] = id_
2416 #fill tenants_datacenters table
2417 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2418 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2419 return datacenter_id
2421 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2422 #get datacenter info
2423 if utils
.check_valid_uuid(datacenter
):
2424 vims
= get_vim(mydb
, datacenter_id
=datacenter
)
2426 vims
= get_vim(mydb
, datacenter_name
=datacenter
)
2428 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2430 #print "nfvo.datacenter_action() error. Several datacenters found"
2431 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2432 datacenter_id
=vims
.keys()[0]
2433 myvim
=vims
[datacenter_id
]
2435 #get nfvo_tenant info
2436 if not tenant_id
or tenant_id
=="any":
2439 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2440 tenant_uuid
= tenant_dict
['uuid']
2442 #check that this association exist before
2443 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2445 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2446 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2447 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2448 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2450 #delete this association
2451 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2453 #get vim_tenant info and deletes
2455 for tenant_datacenter_item
in tenant_datacenter_list
:
2456 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2457 #try to delete vim:tenant
2459 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2460 if vim_tenant_dict
['created']=='true':
2461 #delete tenant at VIM if created by NFVO
2463 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2464 except vimconn
.vimconnException
as e
:
2465 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2466 logger
.warn(warning
)
2467 except db_base_Exception
as e
:
2468 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2469 pass #the error will be caused because dependencies, vim_tenant can not be deleted
2471 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2473 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2475 #get datacenter info
2476 if utils
.check_valid_uuid(datacenter
):
2477 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2479 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2481 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2483 #print "nfvo.datacenter_action() error. Several datacenters found"
2484 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2485 datacenter_id
=vims
.keys()[0]
2486 myvim
=vims
[datacenter_id
]
2488 if 'net-update' in action_dict
:
2490 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2492 except vimconn
.vimconnException
as e
:
2493 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2494 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2495 #update nets Change from VIM format to NFVO format
2498 net_nfvo
={'datacenter_id': datacenter_id
}
2499 net_nfvo
['name'] = net
['name']
2500 #net_nfvo['description']= net['name']
2501 net_nfvo
['vim_net_id'] = net
['id']
2502 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2503 net_nfvo
['shared'] = net
['shared']
2504 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2505 net_list
.append(net_nfvo
)
2506 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2507 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2509 elif 'net-edit' in action_dict
:
2510 net
= action_dict
['net-edit'].pop('net')
2511 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2512 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2513 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2515 elif 'net-delete' in action_dict
:
2516 net
= action_dict
['net-deelte'].get('net')
2517 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2518 result
= mydb
.delete_row(FROM
='datacenter_nets',
2519 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2523 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2525 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2526 #get datacenter info
2527 if utils
.check_valid_uuid(datacenter
):
2528 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2530 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2532 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2534 #print "nfvo.datacenter_action() error. Several datacenters found"
2535 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2536 datacenter_id
=vims
.keys()[0]
2538 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2539 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2540 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2543 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2544 #get datacenter info
2545 if utils
.check_valid_uuid(datacenter
):
2546 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2548 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2550 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2552 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2553 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2554 datacenter_id
=vims
.keys()[0]
2555 myvim
=vims
[datacenter_id
]
2558 action_dict
= action_dict
["netmap"]
2559 if 'vim_id' in action_dict
:
2560 filter_dict
["id"] = action_dict
['vim_id']
2561 if 'vim_name' in action_dict
:
2562 filter_dict
["name"] = action_dict
['vim_name']
2564 filter_dict
["shared"] = True
2567 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
2568 except vimconn
.vimconnException
as e
:
2569 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
2570 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2571 if len(vim_nets
)>1 and action_dict
:
2572 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
2573 elif len(vim_nets
)==0: # and action_dict:
2574 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
2576 for net
in vim_nets
:
2577 net_nfvo
={'datacenter_id': datacenter_id
}
2578 if action_dict
and "name" in action_dict
:
2579 net_nfvo
['name'] = action_dict
['name']
2581 net_nfvo
['name'] = net
['name']
2582 #net_nfvo['description']= net['name']
2583 net_nfvo
['vim_net_id'] = net
['id']
2584 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2585 net_nfvo
['shared'] = net
['shared']
2586 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2588 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2589 net_nfvo
["status"] = "OK"
2590 net_nfvo
["uuid"] = net_id
2591 except db_base_Exception
as e
:
2595 net_nfvo
["status"] = "FAIL: " + str(e
)
2596 net_list
.append(net_nfvo
)
2599 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2600 #get datacenter info
2601 if utils
.check_valid_uuid(datacenter
):
2602 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2604 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2606 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2608 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2609 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2610 datacenter_id
=vims
.keys()[0]
2611 myvim
=vims
[datacenter_id
]
2614 if utils
.check_valid_uuid(name
):
2615 filter_dict
["id"] = name
2617 filter_dict
["name"] = name
2619 if item
=="networks":
2620 #filter_dict['tenant_id'] = myvim['tenant_id']
2621 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2622 elif item
=="tenants":
2623 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2625 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2626 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
2627 if name
and len(content
)==1:
2628 return {item
[:-1]: content
[0]}
2629 elif name
and len(content
)==0:
2630 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
2633 return {item
: content
}
2634 except vimconn
.vimconnException
as e
:
2635 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
2636 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
2638 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
2639 #get datacenter info
2640 if tenant_id
== "any":
2643 if utils
.check_valid_uuid(datacenter
):
2644 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2646 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2648 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2650 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2651 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2652 datacenter_id
=vims
.keys()[0]
2653 myvim
=vims
[datacenter_id
]
2655 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2656 logger
.debug("vim_action_delete vim response: " + str(content
))
2657 items
= content
.values()[0]
2658 if type(items
)==list and len(items
)==0:
2659 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
2660 elif type(items
)==list and len(items
)>1:
2661 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
2662 else: # it is a dict
2663 item_id
= items
["id"]
2664 item_name
= str(items
.get("name"))
2667 if item
=="networks":
2668 content
= myvim
.delete_network(item_id
)
2669 elif item
=="tenants":
2670 content
= myvim
.delete_tenant(item_id
)
2672 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2673 except vimconn
.vimconnException
as e
:
2674 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
2675 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
2677 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
2679 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2680 #get datacenter info
2681 print "vim_action_create descriptor", descriptor
2682 if tenant_id
== "any":
2685 if utils
.check_valid_uuid(datacenter
):
2686 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2688 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2690 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2692 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2693 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2694 datacenter_id
=vims
.keys()[0]
2695 myvim
=vims
[datacenter_id
]
2698 if item
=="networks":
2699 net
= descriptor
["network"]
2700 net_name
= net
.pop("name")
2701 net_type
= net
.pop("type", "bridge")
2702 net_public
= net
.pop("shared", False)
2703 net_ipprofile
= net
.pop("ip_profile", None)
2704 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, **net
)
2705 elif item
=="tenants":
2706 tenant
= descriptor
["tenant"]
2707 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2709 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2710 except vimconn
.vimconnException
as e
:
2711 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
2713 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)