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 if 'ip_profile' not in scenario_net
:
1772 scenario_net
['ip_profile'] = ipprofile
1774 update(scenario_net
['ip_profile'],ipprofile
)
1775 for interface
in net_instance_desc
.get('interfaces', () ):
1776 if 'ip_address' in interface
:
1777 for vnf
in scenarioDict
['vnfs']:
1778 if interface
['vnf'] == vnf
['name']:
1779 for vnf_interface
in vnf
['interfaces']:
1780 if interface
['vnf_interface'] == vnf_interface
['external_name']:
1781 vnf_interface
['ip_address']=interface
['ip_address']
1783 #logger.debug("Merged dictionary")
1784 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
1787 #1. Creating new nets (sce_nets) in the VIM"
1788 for sce_net
in scenarioDict
['nets']:
1789 sce_net
["vim_id_sites"]={}
1790 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
1791 net_name
= descriptor_net
.get("vim-network-name")
1792 auxNetDict
['scenario'][sce_net
['uuid']] = {}
1794 sites
= descriptor_net
.get("sites", [ {} ])
1796 if site
.get("datacenter"):
1797 vim
= myvims
[ site
["datacenter"] ]
1798 datacenter_id
= site
["datacenter"]
1800 vim
= myvims
[ default_datacenter_id
]
1801 datacenter_id
= default_datacenter_id
1803 net_type
= sce_net
['type']
1804 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
1805 if sce_net
["external"]:
1807 net_name
= sce_net
["name"]
1808 if "netmap-use" in site
or "netmap-create" in site
:
1809 create_network
= False
1810 lookfor_network
= False
1811 if "netmap-use" in site
:
1812 lookfor_network
= True
1813 if utils
.check_valid_uuid(site
["netmap-use"]):
1814 filter_text
= "scenario id '%s'" % site
["netmap-use"]
1815 lookfor_filter
["id"] = site
["netmap-use"]
1817 filter_text
= "scenario name '%s'" % site
["netmap-use"]
1818 lookfor_filter
["name"] = site
["netmap-use"]
1819 if "netmap-create" in site
:
1820 create_network
= True
1821 net_vim_name
= net_name
1822 if site
["netmap-create"]:
1823 net_vim_name
= site
["netmap-create"]
1825 elif sce_net
['vim_id'] != None:
1826 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
1827 create_network
= False
1828 lookfor_network
= True
1829 lookfor_filter
["id"] = sce_net
['vim_id']
1830 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
1831 #look for network at datacenter and return error
1833 #There is not a netmap, look at datacenter for a net with this name and create if not found
1834 create_network
= True
1835 lookfor_network
= True
1836 lookfor_filter
["name"] = sce_net
["name"]
1837 net_vim_name
= sce_net
["name"]
1838 filter_text
= "scenario name '%s'" % sce_net
["name"]
1841 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
1842 net_name
= net_name
[:255] #limit length
1843 net_vim_name
= net_name
1844 create_network
= True
1845 lookfor_network
= False
1848 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
1849 if len(vim_nets
) > 1:
1850 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1851 elif len(vim_nets
) == 0:
1852 if not create_network
:
1853 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1855 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
1857 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
1858 create_network
= False
1860 #if network is not external
1861 network_id
= vim
.new_network(net_vim_name
, net_type
, sce_net
.get('ip_profile',None))
1862 sce_net
["vim_id_sites"][datacenter_id
] = network_id
1863 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = network_id
1864 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':network_id
})
1865 sce_net
["created"] = True
1867 #2. Creating new nets (vnf internal nets) in the VIM"
1868 #For each vnf net, we create it and we add it to instanceNetlist.
1869 for sce_vnf
in scenarioDict
['vnfs']:
1870 for net
in sce_vnf
['nets']:
1871 if sce_vnf
.get("datacenter"):
1872 vim
= myvims
[ sce_vnf
["datacenter"] ]
1873 datacenter_id
= sce_vnf
["datacenter"]
1875 vim
= myvims
[ default_datacenter_id
]
1876 datacenter_id
= default_datacenter_id
1877 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
1878 net_name
= descriptor_net
.get("name")
1880 net_name
= "%s.%s" %(instance_name
, net
["name"])
1881 net_name
= net_name
[:255] #limit length
1882 net_type
= net
['type']
1883 network_id
= vim
.new_network(net_name
, net_type
, net
.get('ip_profile',None))
1884 net
['vim_id'] = network_id
1885 if sce_vnf
['uuid'] not in auxNetDict
:
1886 auxNetDict
[sce_vnf
['uuid']] = {}
1887 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1888 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1889 net
["created"] = True
1892 #print "auxNetDict:"
1893 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1895 #3. Creating new vm instances in the VIM
1896 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1897 for sce_vnf
in scenarioDict
['vnfs']:
1898 if sce_vnf
.get("datacenter"):
1899 vim
= myvims
[ sce_vnf
["datacenter"] ]
1900 datacenter_id
= sce_vnf
["datacenter"]
1902 vim
= myvims
[ default_datacenter_id
]
1903 datacenter_id
= default_datacenter_id
1904 sce_vnf
["datacenter_id"] = datacenter_id
1905 sce_vnf
["datacenter_tenant_id"] = vim
['config']['datacenter_tenant_id']
1907 for vm
in sce_vnf
['vms']:
1910 myVMDict
['name'] = "%s.%s.%d" % (instance_name
,sce_vnf
['name'],i
)
1911 myVMDict
['description'] = myVMDict
['name'][0:99]
1913 # myVMDict['start'] = "no"
1914 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1915 #create image at vim in case it not exist
1916 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1917 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
1918 vm
['vim_image_id'] = image_id
1920 #create flavor at vim in case it not exist
1921 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1922 if flavor_dict
['extended']!=None:
1923 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1924 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
1925 vm
['vim_flavor_id'] = flavor_id
1927 myVMDict
['imageRef'] = vm
['vim_image_id']
1928 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1929 myVMDict
['networks'] = []
1930 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
1931 for iface
in vm
['interfaces']:
1933 if iface
['type']=="data":
1934 netDict
['type'] = iface
['model']
1935 elif "model" in iface
and iface
["model"]!=None:
1936 netDict
['model']=iface
['model']
1937 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1938 #discover type of interface looking at flavor
1939 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1940 for flavor_iface
in numa
.get('interfaces',[]):
1941 if flavor_iface
.get('name') == iface
['internal_name']:
1942 if flavor_iface
['dedicated'] == 'yes':
1943 netDict
['type']="PF" #passthrough
1944 elif flavor_iface
['dedicated'] == 'no':
1945 netDict
['type']="VF" #siov
1946 elif flavor_iface
['dedicated'] == 'yes:sriov':
1947 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1948 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1950 netDict
["use"]=iface
['type']
1951 if netDict
["use"]=="data" and not netDict
.get("type"):
1952 #print "netDict", netDict
1953 #print "iface", iface
1954 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'])
1955 if flavor_dict
.get('extended')==None:
1956 raise NfvoException(e_text
+ "After database migration some information is not available. \
1957 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1959 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1960 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1961 netDict
["type"]="virtual"
1962 if "vpci" in iface
and iface
["vpci"] is not None:
1963 netDict
['vpci'] = iface
['vpci']
1964 if "mac" in iface
and iface
["mac"] is not None:
1965 netDict
['mac_address'] = iface
['mac']
1966 netDict
['name'] = iface
['internal_name']
1967 if iface
['net_id'] is None:
1968 for vnf_iface
in sce_vnf
["interfaces"]:
1971 if vnf_iface
['interface_id']==iface
['uuid']:
1972 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
1975 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1976 #skip bridge ifaces not connected to any net
1977 #if 'net_id' not in netDict or netDict['net_id']==None:
1979 myVMDict
['networks'].append(netDict
)
1980 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1981 #print myVMDict['name']
1982 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1983 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1984 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1985 vm_id
= vim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1986 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'], cloud_config
= cloud_config
)
1987 vm
['vim_id'] = vm_id
1988 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1989 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1990 for net
in myVMDict
['networks']:
1992 for iface
in vm
['interfaces']:
1993 if net
["name"]==iface
["internal_name"]:
1994 iface
["vim_id"]=net
["vim_id"]
1996 logger
.debug("create_instance Deployment done")
1997 print yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)
1998 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1999 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
2000 return mydb
.get_instance_scenario(instance_id
)
2001 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2002 message
= rollback(mydb
, myvims
, rollbackList
)
2003 if isinstance(e
, db_base_Exception
):
2004 error_text
= "database Exception"
2005 elif isinstance(e
, vimconn
.vimconnException
):
2006 error_text
= "VIM Exception"
2008 error_text
= "Exception"
2009 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2010 #logger.error("create_instance: %s", error_text)
2011 raise NfvoException(error_text
, e
.http_code
)
2013 def delete_instance(mydb
, tenant_id
, instance_id
):
2014 #print "Checking that the instance_id exists and getting the instance dictionary"
2015 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2016 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2017 tenant_id
= instanceDict
["tenant_id"]
2018 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2020 vims
= get_vim(mydb
, tenant_id
, instanceDict
['datacenter_id'])
2022 logger
.error("!!!!!! nfvo.delete_instance() datacenter not found!!!!")
2025 myvim
= vims
.values()[0]
2026 except NfvoException
as e
:
2027 logger
.error("!!!!!! nfvo.delete_instance() datacenter Exception!!!! " + str(e
))
2031 #1. Delete from Database
2033 #result,c = mydb.delete_row_by_id('instance_scenarios', instance_id, nfvo_tenant)
2034 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2038 error_msg
= "Not possible to delete VIM VMs and networks. Datacenter not found at database!!!"
2044 for sce_vnf
in instanceDict
['vnfs']:
2047 for vm
in sce_vnf
['vms']:
2049 myvim
.delete_vminstance(vm
['vim_vm_id'])
2050 except vimconn
.vimconnNotFoundException
as e
:
2051 error_msg
+="\n VM id={} not found at VIM".format(vm
['vim_vm_id'])
2052 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2053 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2054 except vimconn
.vimconnException
as e
:
2055 error_msg
+="\n Error: " + e
.http_code
+ " VM id=" + vm
['vim_vm_id']
2056 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s': %s",
2057 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2061 for net
in instanceDict
['nets']:
2062 if not net
['created']:
2063 continue #skip not created nets
2067 myvim
.delete_network(net
['vim_net_id'])
2068 except vimconn
.vimconnNotFoundException
as e
:
2069 error_msg
+="\n NET id={} not found at VIM".format(net
['vim_net_id'])
2070 logger
.warn("NET '%s', VIM id '%s', from VNF_id '%s' not found",
2071 net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'])
2072 except vimconn
.vimconnException
as e
:
2073 error_msg
+="\n Error: " + e
.http_code
+ " Net id=" + net
['vim_vm_id']
2074 logger
.error("Error %d deleting NET '%s', VIM id '%s', from VNF_id '%s': %s",
2075 e
.http_code
, net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'], str(e
))
2076 if len(error_msg
)>0:
2077 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2079 return 'instance ' + message
+ ' deleted'
2081 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2082 '''Refreshes a scenario instance. It modifies instanceDict'''
2084 - 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
2087 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2088 #print "nfvo.refresh_instance begins"
2089 #print json.dumps(instanceDict, indent=4)
2091 #print "Getting the VIM URL and the VIM tenant_id"
2092 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2094 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2095 myvim
= vims
.values()[0]
2097 # 1. Getting VIM vm and net list
2098 vms_updated
= [] #List of VM instance uuids in openmano that were updated
2101 for sce_vnf
in instanceDict
['vnfs']:
2102 for vm
in sce_vnf
['vms']:
2103 vm_list
.append(vm
['vim_vm_id'])
2104 vms_notupdated
.append(vm
["uuid"])
2106 nets_updated
= [] #List of VM instance uuids in openmano that were updated
2109 for net
in instanceDict
['nets']:
2110 net_list
.append(net
['vim_net_id'])
2111 nets_notupdated
.append(net
["uuid"])
2114 # 1. Getting the status of all VMs
2115 vm_dict
= myvim
.refresh_vms_status(vm_list
)
2117 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2118 for sce_vnf
in instanceDict
['vnfs']:
2119 for vm
in sce_vnf
['vms']:
2120 vm_id
= vm
['vim_vm_id']
2121 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
2122 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2123 has_mgmt_iface
= False
2124 for iface
in vm
["interfaces"]:
2125 if iface
["type"]=="mgmt":
2126 has_mgmt_iface
= True
2127 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
2128 vm_dict
[vm_id
]['status'] = "ACTIVE"
2129 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'):
2130 vm
['status'] = vm_dict
[vm_id
]['status']
2131 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
2132 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
2133 # 2.1. Update in openmano DB the VMs whose status changed
2135 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
2136 vms_notupdated
.remove(vm
["uuid"])
2138 vms_updated
.append(vm
["uuid"])
2139 except db_base_Exception
as e
:
2140 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2141 # 2.2. Update in openmano DB the interface VMs
2142 for interface
in interfaces
:
2143 #translate from vim_net_id to instance_net_id
2145 for net
in instanceDict
['nets']:
2146 if net
["vim_net_id"] == interface
["vim_net_id"]:
2147 network_id_list
.append(net
["uuid"])
2148 if not network_id_list
:
2150 del interface
["vim_net_id"]
2152 for network_id
in network_id_list
:
2153 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
2154 except db_base_Exception
as e
:
2155 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
2157 # 3. Getting the status of all nets
2158 net_dict
= myvim
.refresh_nets_status(net_list
)
2160 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2161 # TODO: update nets inside a vnf
2162 for net
in instanceDict
['nets']:
2163 net_id
= net
['vim_net_id']
2164 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'):
2165 net
['status'] = net_dict
[net_id
]['status']
2166 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
2167 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
2168 # 5.1. Update in openmano DB the nets whose status changed
2170 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
2171 nets_notupdated
.remove(net
["uuid"])
2173 nets_updated
.append(net
["uuid"])
2174 except db_base_Exception
as e
:
2175 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2176 except vimconn
.vimconnException
as e
:
2177 #logger.error("VIM exception %s %s", type(e).__name__, str(e))
2178 raise NfvoException(str(e
), e
.http_code
)
2180 # Returns appropriate output
2181 #print "nfvo.refresh_instance finishes"
2182 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2183 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
2184 instance_id
= instanceDict
['uuid']
2185 if len(vms_notupdated
)+len(nets_notupdated
)>0:
2186 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
2187 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
2189 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2191 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2192 #print "Checking that the instance_id exists and getting the instance dictionary"
2193 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2194 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2196 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2197 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2199 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2200 myvim
= vims
.values()[0]
2203 input_vnfs
= action_dict
.pop("vnfs", [])
2204 input_vms
= action_dict
.pop("vms", [])
2205 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2209 for sce_vnf
in instanceDict
['vnfs']:
2210 for vm
in sce_vnf
['vms']:
2211 if not action_over_all
:
2212 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2213 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2216 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2217 if "console" in action_dict
:
2218 if not global_config
["http_console_proxy"]:
2219 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2220 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2221 protocol
=data
["protocol"],
2222 ip
= data
["server"],
2223 port
= data
["port"],
2224 suffix
= data
["suffix"]),
2228 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2229 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2230 "description": "this console is only reachable by local interface",
2235 #print "console data", data
2237 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2238 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2239 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2240 protocol
=data
["protocol"],
2241 ip
= global_config
["http_console_host"],
2242 port
= console_thread
.port
,
2243 suffix
= data
["suffix"]),
2247 except NfvoException
as e
:
2248 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2252 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2254 except vimconn
.vimconnException
as e
:
2255 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2258 if vm_ok
==0: #all goes wrong
2263 def create_or_use_console_proxy_thread(console_server
, console_port
):
2264 #look for a non-used port
2265 console_thread_key
= console_server
+ ":" + str(console_port
)
2266 if console_thread_key
in global_config
["console_thread"]:
2267 #global_config["console_thread"][console_thread_key].start_timeout()
2268 return global_config
["console_thread"][console_thread_key
]
2270 for port
in global_config
["console_port_iterator"]():
2271 #print "create_or_use_console_proxy_thread() port:", port
2272 if port
in global_config
["console_ports"]:
2275 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2277 global_config
["console_thread"][console_thread_key
] = clithread
2278 global_config
["console_ports"][port
] = console_thread_key
2280 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2281 #port used, try with onoher
2283 except cli
.ConsoleProxyException
as e
:
2284 raise NfvoException(str(e
), HTTP_Bad_Request
)
2285 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2287 def check_tenant(mydb
, tenant_id
):
2288 '''check that tenant exists at database'''
2289 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2291 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2294 def new_tenant(mydb
, tenant_dict
):
2295 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2298 def delete_tenant(mydb
, tenant
):
2299 #get nfvo_tenant info
2301 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2302 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2303 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2305 def new_datacenter(mydb
, datacenter_descriptor
):
2306 if "config" in datacenter_descriptor
:
2307 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2308 #Check that datacenter-type is correct
2309 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2312 module
= "vimconn_" + datacenter_type
2313 module_info
= imp
.find_module(module
)
2314 except (IOError, ImportError):
2315 if module_info
and module_info
[0]:
2316 file.close(module_info
[0])
2317 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2319 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2320 return datacenter_id
2322 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2323 #obtain data, check that only one exist
2324 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2326 datacenter_id
= datacenter
['uuid']
2327 where
={'uuid': datacenter
['uuid']}
2328 if "config" in datacenter_descriptor
:
2329 if datacenter_descriptor
['config']!=None:
2331 new_config_dict
= datacenter_descriptor
["config"]
2334 for k
in new_config_dict
:
2335 if new_config_dict
[k
]==None:
2338 config_dict
= yaml
.load(datacenter
["config"])
2339 config_dict
.update(new_config_dict
)
2343 except Exception as e
:
2344 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2345 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2346 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2347 return datacenter_id
2349 def delete_datacenter(mydb
, datacenter
):
2350 #get nfvo_tenant info
2351 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2352 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2353 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2355 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None):
2356 #get datacenter info
2357 if utils
.check_valid_uuid(datacenter
):
2358 vims
= get_vim(mydb
, datacenter_id
=datacenter
, vim_tenant_name
=vim_tenant_name
, vim_user
=vim_username
, vim_passwd
=vim_password
)
2360 vims
= get_vim(mydb
, datacenter_name
=datacenter
, vim_tenant_name
=vim_tenant_name
, vim_user
=vim_username
, vim_passwd
=vim_password
)
2362 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2364 #print "nfvo.datacenter_action() error. Several datacenters found"
2365 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2367 datacenter_id
=vims
.keys()[0]
2368 myvim
=vims
[datacenter_id
]
2369 datacenter_name
=myvim
["name"]
2371 create_vim_tenant
=True if vim_tenant_id
==None and vim_tenant_name
==None else False
2373 #get nfvo_tenant info
2374 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2375 if vim_tenant_name
==None:
2376 vim_tenant_name
=tenant_dict
['name']
2378 #check that this association does not exist before
2379 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2380 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2381 if len(tenants_datacenters
)>0:
2382 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2384 vim_tenant_id_exist_atdb
=False
2385 if not create_vim_tenant
:
2386 where_
={"datacenter_id": datacenter_id
}
2387 if vim_tenant_id
!=None:
2388 where_
["vim_tenant_id"] = vim_tenant_id
2389 if vim_tenant_name
!=None:
2390 where_
["vim_tenant_name"] = vim_tenant_name
2391 #check if vim_tenant_id is already at database
2392 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2393 if len(datacenter_tenants_dict
)>=1:
2394 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2395 vim_tenant_id_exist_atdb
=True
2396 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2398 datacenter_tenants_dict
= {}
2399 #insert at table datacenter_tenants
2400 else: #if vim_tenant_id==None:
2401 #create tenant at VIM if not provided
2403 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2404 except vimconn
.vimconnException
as e
:
2405 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2406 datacenter_tenants_dict
= {}
2407 datacenter_tenants_dict
["created"]="true"
2409 #fill datacenter_tenants table
2410 if not vim_tenant_id_exist_atdb
:
2411 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2412 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2413 datacenter_tenants_dict
["user"] = vim_username
2414 datacenter_tenants_dict
["passwd"] = vim_password
2415 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2416 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2417 datacenter_tenants_dict
["uuid"] = id_
2419 #fill tenants_datacenters table
2420 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2421 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2422 return datacenter_id
2424 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2425 #get datacenter info
2426 if utils
.check_valid_uuid(datacenter
):
2427 vims
= get_vim(mydb
, datacenter_id
=datacenter
)
2429 vims
= get_vim(mydb
, datacenter_name
=datacenter
)
2431 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2433 #print "nfvo.datacenter_action() error. Several datacenters found"
2434 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2435 datacenter_id
=vims
.keys()[0]
2436 myvim
=vims
[datacenter_id
]
2438 #get nfvo_tenant info
2439 if not tenant_id
or tenant_id
=="any":
2442 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2443 tenant_uuid
= tenant_dict
['uuid']
2445 #check that this association exist before
2446 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2448 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2449 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2450 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2451 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2453 #delete this association
2454 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2456 #get vim_tenant info and deletes
2458 for tenant_datacenter_item
in tenant_datacenter_list
:
2459 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2460 #try to delete vim:tenant
2462 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2463 if vim_tenant_dict
['created']=='true':
2464 #delete tenant at VIM if created by NFVO
2466 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2467 except vimconn
.vimconnException
as e
:
2468 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2469 logger
.warn(warning
)
2470 except db_base_Exception
as e
:
2471 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2472 pass #the error will be caused because dependencies, vim_tenant can not be deleted
2474 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2476 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2478 #get datacenter info
2479 if utils
.check_valid_uuid(datacenter
):
2480 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2482 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2484 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2486 #print "nfvo.datacenter_action() error. Several datacenters found"
2487 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2488 datacenter_id
=vims
.keys()[0]
2489 myvim
=vims
[datacenter_id
]
2491 if 'net-update' in action_dict
:
2493 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2495 except vimconn
.vimconnException
as e
:
2496 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2497 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2498 #update nets Change from VIM format to NFVO format
2501 net_nfvo
={'datacenter_id': datacenter_id
}
2502 net_nfvo
['name'] = net
['name']
2503 #net_nfvo['description']= net['name']
2504 net_nfvo
['vim_net_id'] = net
['id']
2505 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2506 net_nfvo
['shared'] = net
['shared']
2507 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2508 net_list
.append(net_nfvo
)
2509 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2510 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2512 elif 'net-edit' in action_dict
:
2513 net
= action_dict
['net-edit'].pop('net')
2514 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2515 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2516 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2518 elif 'net-delete' in action_dict
:
2519 net
= action_dict
['net-deelte'].get('net')
2520 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2521 result
= mydb
.delete_row(FROM
='datacenter_nets',
2522 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2526 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2528 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2529 #get datacenter info
2530 if utils
.check_valid_uuid(datacenter
):
2531 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2533 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2535 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2537 #print "nfvo.datacenter_action() error. Several datacenters found"
2538 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2539 datacenter_id
=vims
.keys()[0]
2541 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2542 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2543 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2546 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2547 #get datacenter info
2548 if utils
.check_valid_uuid(datacenter
):
2549 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2551 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2553 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2555 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2556 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2557 datacenter_id
=vims
.keys()[0]
2558 myvim
=vims
[datacenter_id
]
2561 action_dict
= action_dict
["netmap"]
2562 if 'vim_id' in action_dict
:
2563 filter_dict
["id"] = action_dict
['vim_id']
2564 if 'vim_name' in action_dict
:
2565 filter_dict
["name"] = action_dict
['vim_name']
2567 filter_dict
["shared"] = True
2570 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
2571 except vimconn
.vimconnException
as e
:
2572 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
2573 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2574 if len(vim_nets
)>1 and action_dict
:
2575 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
2576 elif len(vim_nets
)==0: # and action_dict:
2577 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
2579 for net
in vim_nets
:
2580 net_nfvo
={'datacenter_id': datacenter_id
}
2581 if action_dict
and "name" in action_dict
:
2582 net_nfvo
['name'] = action_dict
['name']
2584 net_nfvo
['name'] = net
['name']
2585 #net_nfvo['description']= net['name']
2586 net_nfvo
['vim_net_id'] = net
['id']
2587 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2588 net_nfvo
['shared'] = net
['shared']
2589 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2591 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2592 net_nfvo
["status"] = "OK"
2593 net_nfvo
["uuid"] = net_id
2594 except db_base_Exception
as e
:
2598 net_nfvo
["status"] = "FAIL: " + str(e
)
2599 net_list
.append(net_nfvo
)
2602 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2603 #get datacenter info
2604 if utils
.check_valid_uuid(datacenter
):
2605 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2607 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2609 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2611 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2612 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2613 datacenter_id
=vims
.keys()[0]
2614 myvim
=vims
[datacenter_id
]
2617 if utils
.check_valid_uuid(name
):
2618 filter_dict
["id"] = name
2620 filter_dict
["name"] = name
2622 if item
=="networks":
2623 #filter_dict['tenant_id'] = myvim['tenant_id']
2624 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2625 elif item
=="tenants":
2626 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2628 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2629 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
2630 if name
and len(content
)==1:
2631 return {item
[:-1]: content
[0]}
2632 elif name
and len(content
)==0:
2633 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
2636 return {item
: content
}
2637 except vimconn
.vimconnException
as e
:
2638 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
2639 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
2641 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
2642 #get datacenter info
2643 if tenant_id
== "any":
2646 if utils
.check_valid_uuid(datacenter
):
2647 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2649 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2651 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2653 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2654 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2655 datacenter_id
=vims
.keys()[0]
2656 myvim
=vims
[datacenter_id
]
2658 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2659 logger
.debug("vim_action_delete vim response: " + str(content
))
2660 items
= content
.values()[0]
2661 if type(items
)==list and len(items
)==0:
2662 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
2663 elif type(items
)==list and len(items
)>1:
2664 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
2665 else: # it is a dict
2666 item_id
= items
["id"]
2667 item_name
= str(items
.get("name"))
2670 if item
=="networks":
2671 content
= myvim
.delete_network(item_id
)
2672 elif item
=="tenants":
2673 content
= myvim
.delete_tenant(item_id
)
2675 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2676 except vimconn
.vimconnException
as e
:
2677 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
2678 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
2680 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
2682 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2683 #get datacenter info
2684 print "vim_action_create descriptor", descriptor
2685 if tenant_id
== "any":
2688 if utils
.check_valid_uuid(datacenter
):
2689 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2691 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2693 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2695 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2696 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2697 datacenter_id
=vims
.keys()[0]
2698 myvim
=vims
[datacenter_id
]
2701 if item
=="networks":
2702 net
= descriptor
["network"]
2703 net_name
= net
.pop("name")
2704 net_type
= net
.pop("type", "bridge")
2705 net_public
= net
.pop("shared", False)
2706 net_ipprofile
= net
.pop("ip_profile", None)
2707 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, **net
)
2708 elif item
=="tenants":
2709 tenant
= descriptor
["tenant"]
2710 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2712 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2713 except vimconn
.vimconnException
as e
:
2714 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
2716 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)