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, datacenter_tenant_id
=None,
96 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
97 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
98 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
99 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
100 raise exception upon error
103 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
104 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
105 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
106 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
107 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
108 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
109 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
110 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'
111 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
112 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
115 from_
= 'datacenters as d'
116 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
118 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
121 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
122 if vim
["config"] != None:
123 extra
.update(yaml
.load(vim
["config"]))
124 if vim
["type"] not in vimconn_imported
:
127 module
= "vimconn_" + vim
["type"]
128 module_info
= imp
.find_module(module
)
129 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
130 vimconn_imported
[vim
["type"]] = vim_conn
131 except (IOError, ImportError) as e
:
132 if module_info
and module_info
[0]:
133 file.close(module_info
[0])
134 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
135 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
139 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
140 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
141 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
142 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
), tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
143 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
144 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
147 except Exception as e
:
148 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
150 except db_base_Exception
as e
:
151 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
153 def rollback(mydb
, vims
, rollback_list
):
155 #delete things by reverse order
156 for i
in range(len(rollback_list
)-1, -1, -1):
157 item
= rollback_list
[i
]
158 if item
["where"]=="vim":
159 if item
["vim_id"] not in vims
:
161 vim
=vims
[ item
["vim_id"] ]
163 if item
["what"]=="image":
164 vim
.delete_image(item
["uuid"])
165 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
166 elif item
["what"]=="flavor":
167 vim
.delete_flavor(item
["uuid"])
168 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
169 elif item
["what"]=="network":
170 vim
.delete_network(item
["uuid"])
171 elif item
["what"]=="vm":
172 vim
.delete_vminstance(item
["uuid"])
173 except vimconn
.vimconnException
as e
:
174 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
175 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
176 except db_base_Exception
as e
:
177 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
181 if item
["what"]=="image":
182 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
183 elif item
["what"]=="flavor":
184 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
185 except db_base_Exception
as e
:
186 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
187 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
188 if len(undeleted_items
)==0:
189 return True," Rollback successful."
191 return False," Rollback fails to delete: " + str(undeleted_items
)
193 def check_vnf_descriptor(vnf_descriptor
):
195 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
197 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
199 #dataplane interfaces
200 for numa
in vnfc
.get("numas",() ):
201 for interface
in numa
.get("interfaces",()):
202 if interface
["name"] in name_list
:
203 raise NfvoException("Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC"\
204 .format(vnfc
["name"], interface
["name"]),
206 name_list
.append( interface
["name"] )
208 for interface
in vnfc
.get("bridge-ifaces",() ):
209 if interface
["name"] in name_list
:
210 raise NfvoException("Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC"\
211 .format(vnfc
["name"], interface
["name"]),
213 name_list
.append( interface
["name"] )
214 vnfc_interfaces
[ vnfc
["name"] ] = name_list
216 #check if the info in external_connections matches with the one in the vnfcs
218 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
219 if external_connection
["name"] in name_list
:
220 raise NfvoException("Error at vnf:external-connections:name, value '{}' already used as an external-connection"\
221 .format(external_connection
["name"]),
223 name_list
.append(external_connection
["name"])
224 if external_connection
["VNFC"] not in vnfc_interfaces
:
225 raise NfvoException("Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC"\
226 .format(external_connection
["name"], external_connection
["VNFC"]),
229 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
230 raise NfvoException("Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC"\
231 .format(external_connection
["name"], external_connection
["local_iface_name"]),
234 #check if the info in internal_connections matches with the one in the vnfcs
236 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
237 if internal_connection
["name"] in name_list
:
238 raise NfvoException("Error at vnf:internal-connections:name, value '%s' already used as an internal-connection"\
239 .format(internal_connection
["name"]),
241 name_list
.append(internal_connection
["name"])
242 #We should check that internal-connections of type "ptp" have only 2 elements
243 if len(internal_connection
["elements"])>2 and internal_connection
["type"] == "ptp":
244 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements, size must be 2 for a type:'ptp'"\
245 .format(internal_connection
["name"]),
247 for port
in internal_connection
["elements"]:
248 if port
["VNFC"] not in vnfc_interfaces
:
249 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC"\
250 .format(internal_connection
["name"], port
["VNFC"]),
252 if port
["local_iface_name"] not in vnfc_interfaces
[ port
["VNFC"] ]:
253 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC"\
254 .format(internal_connection
["name"], port
["local_iface_name"]),
256 return -HTTP_Bad_Request
,
258 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
260 if only_create_at_vim
:
261 image_mano_id
= image_dict
['uuid']
263 if image_dict
['location'] is not None:
264 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
266 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
268 image_mano_id
= images
[0]['uuid']
271 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
272 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
273 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
275 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
276 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
277 #create image at every vim
278 for vim_id
,vim
in vims
.iteritems():
279 image_created
="false"
281 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
282 #look at VIM if this image exist
284 if image_dict
['location'] is not None:
285 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
288 filter_dict
['name']=image_dict
['universal_name']
289 filter_dict
['checksum']=image_dict
['checksum']
290 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
291 vim_images
= vim
.get_image_list(filter_dict
)
292 if len(vim_images
) > 1:
293 raise NfvoException("More than one candidate VIM image found for filter: " + str(filter_dict
), HTTP_Conflict
)
294 elif len(vim_images
) == 0:
295 raise NfvoException("Image not found at VIM with filter: '%s'", str(filter_dict
))
297 image_vim_id
= vim_images
[0].id
299 except vimconn
.vimconnNotFoundException
as e
:
300 #Create the image in VIM
302 image_vim_id
= vim
.new_image(image_dict
)
303 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
305 except vimconn
.vimconnException
as e
:
307 logger
.error("Error creating image at VIM: %s", str(e
))
309 image_vim_id
= str(e
)
310 logger
.warn("Error creating image at VIM: %s", str(e
))
312 except vimconn
.vimconnException
as e
:
313 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
314 image_vim_id
= str(e
)
316 #if we reach here, the image has been created or existed
318 #add new vim_id at datacenters_images
319 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
320 elif image_db
[0]["vim_id"]!=image_vim_id
:
321 #modify existing vim_id at datacenters_images
322 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
324 return image_vim_id
if only_create_at_vim
else image_mano_id
326 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
327 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
328 'ram':flavor_dict
.get('ram'),
329 'vcpus':flavor_dict
.get('vcpus'),
331 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
332 del flavor_dict
['extended']
333 if 'extended' in flavor_dict
:
334 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
336 #look if flavor exist
337 if only_create_at_vim
:
338 flavor_mano_id
= flavor_dict
['uuid']
340 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
342 flavor_mano_id
= flavors
[0]['uuid']
345 #create one by one the images of aditional disks
346 dev_image_list
=[] #list of images
347 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
349 for device
in flavor_dict
['extended'].get('devices',[]):
350 if "image" not in device
or "image name" not in device
:
353 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
354 image_dict
['universal_name']=device
.get('image name')
355 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
356 image_dict
['location']=device
.get('image')
357 image_dict
['checksum']=device
.get('image checksum')
358 image_metadata_dict
= device
.get('image metadata', None)
359 image_metadata_str
= None
360 if image_metadata_dict
!= None:
361 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
362 image_dict
['metadata']=image_metadata_str
363 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
364 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
365 dev_image_list
.append(image_id
)
367 temp_flavor_dict
['name'] = flavor_dict
['name']
368 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
369 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
370 flavor_mano_id
= content
371 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
372 #create flavor at every vim
373 if 'uuid' in flavor_dict
:
374 del flavor_dict
['uuid']
376 for vim_id
,vim
in vims
.items():
377 flavor_created
="false"
379 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
380 #look at VIM if this flavor exist SKIPPED
381 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
383 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
387 #Create the flavor in VIM
388 #Translate images at devices from MANO id to VIM id
389 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
390 #make a copy of original devices
392 for device
in flavor_dict
["extended"].get("devices",[]):
395 devices_original
.append(dev
)
396 if 'image' in device
:
398 if 'image metadata' in device
:
399 del device
['image metadata']
401 for index
in range(0,len(devices_original
)) :
402 device
=devices_original
[index
]
403 if "image" not in device
or "image name" not in device
:
406 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
407 image_dict
['universal_name']=device
.get('image name')
408 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
409 image_dict
['location']=device
.get('image')
410 image_dict
['checksum']=device
.get('image checksum')
411 image_metadata_dict
= device
.get('image metadata', None)
412 image_metadata_str
= None
413 if image_metadata_dict
!= None:
414 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
415 image_dict
['metadata']=image_metadata_str
416 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
417 image_dict
["uuid"]=image_mano_id
418 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
419 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
422 #check that this vim_id exist in VIM, if not create
423 flavor_vim_id
=flavor_db
[0]["vim_id"]
425 vim
.get_flavor(flavor_vim_id
)
426 continue #flavor exist
427 except vimconn
.vimconnException
:
429 #create flavor at vim
430 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
432 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
433 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
434 flavor_created
="true"
435 except vimconn
.vimconnException
as e
:
437 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
439 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
441 #if reach here the flavor has been create or exist
442 if len(flavor_db
)==0:
443 #add new vim_id at datacenters_flavors
444 mydb
.new_row('datacenters_flavors', {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
, 'created':flavor_created
})
445 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
446 #modify existing vim_id at datacenters_flavors
447 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
449 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
451 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
454 # Step 1. Check the VNF descriptor
455 check_vnf_descriptor(vnf_descriptor
)
456 # Step 2. Check tenant exist
457 if tenant_id
!= "any":
458 check_tenant(mydb
, tenant_id
)
459 if "tenant_id" in vnf_descriptor
["vnf"]:
460 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
461 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
464 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
465 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
466 vims
= get_vim(mydb
, tenant_id
)
470 # Step 4. Review the descriptor and add missing fields
471 #print vnf_descriptor
472 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
473 vnf_name
= vnf_descriptor
['vnf']['name']
474 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
475 if "physical" in vnf_descriptor
['vnf']:
476 del vnf_descriptor
['vnf']['physical']
477 #print vnf_descriptor
478 # Step 5. Check internal connections
479 # TODO: to be moved to step 1????
480 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
481 for ic
in internal_connections
:
482 if len(ic
['elements'])>2 and ic
['type']=='ptp':
483 raise NfvoException("Mismatch 'type':'ptp' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'data'".format(len(ic
), ic
['name']),
485 elif len(ic
['elements'])==2 and ic
['type']=='data':
486 raise NfvoException("Mismatch 'type':'data' with 2 elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'ptp'".format(ic
['name']),
489 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
490 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
491 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
493 #For each VNFC, we add it to the VNFCDict and we create a flavor.
494 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
495 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
497 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
498 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
500 VNFCitem
["name"] = vnfc
['name']
501 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
503 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
506 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
507 myflavorDict
["description"] = VNFCitem
["description"]
508 myflavorDict
["ram"] = vnfc
.get("ram", 0)
509 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
510 myflavorDict
["disk"] = vnfc
.get("disk", 1)
511 myflavorDict
["extended"] = {}
513 devices
= vnfc
.get("devices")
515 myflavorDict
["extended"]["devices"] = devices
518 # 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
519 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
521 # Previous code has been commented
522 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
523 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
524 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
525 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
527 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
529 # print "Error creating flavor: unknown processor model. Rollback successful."
530 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
532 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
533 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
535 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
536 myflavorDict
['extended']['numas'] = vnfc
['numas']
540 # Step 6.2 New flavors are created in the VIM
541 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
543 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
544 VNFCitem
["flavor_id"] = flavor_id
545 VNFCDict
[vnfc
['name']] = VNFCitem
547 logger
.debug("Creating new images in the VIM for each VNFC")
548 # Step 6.3 New images are created in the VIM
549 #For each VNFC, we must create the appropriate image.
550 #This "for" loop might be integrated with the previous one
551 #In case this integration is made, the VNFCDict might become a VNFClist.
552 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
553 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
555 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
556 image_dict
['universal_name']=vnfc
.get('image name')
557 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
558 image_dict
['location']=vnfc
.get('VNFC image')
559 image_dict
['checksum']=vnfc
.get('image checksum')
560 image_metadata_dict
= vnfc
.get('image metadata', None)
561 image_metadata_str
= None
562 if image_metadata_dict
is not None:
563 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
564 image_dict
['metadata']=image_metadata_str
565 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
566 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
567 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
568 VNFCDict
[vnfc
['name']]["image_id"] = image_id
569 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
572 # Step 7. Storing the VNF descriptor in the repository
573 if "descriptor" not in vnf_descriptor
["vnf"]:
574 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
576 # Step 8. Adding the VNF to the NFVO DB
577 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
579 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
580 _
, message
= rollback(mydb
, vims
, rollback_list
)
581 if isinstance(e
, db_base_Exception
):
582 error_text
= "Exception at database"
583 elif isinstance(e
, KeyError):
584 error_text
= "KeyError exception "
585 e
.http_code
= HTTP_Internal_Server_Error
587 error_text
= "Exception at VIM"
588 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
589 #logger.error("start_scenario %s", error_text)
590 raise NfvoException(error_text
, e
.http_code
)
592 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
595 # Step 1. Check the VNF descriptor
596 check_vnf_descriptor(vnf_descriptor
)
597 # Step 2. Check tenant exist
598 if tenant_id
!= "any":
599 check_tenant(mydb
, tenant_id
)
600 if "tenant_id" in vnf_descriptor
["vnf"]:
601 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
602 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
605 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
606 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
607 vims
= get_vim(mydb
, tenant_id
)
611 # Step 4. Review the descriptor and add missing fields
612 #print vnf_descriptor
613 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
614 vnf_name
= vnf_descriptor
['vnf']['name']
615 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
616 if "physical" in vnf_descriptor
['vnf']:
617 del vnf_descriptor
['vnf']['physical']
618 #print vnf_descriptor
619 # Step 5. Check internal connections
620 # TODO: to be moved to step 1????
621 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
622 for ic
in internal_connections
:
623 if len(ic
['elements'])>2 and ic
['type']=='e-line':
624 raise NfvoException("Mismatch 'type':'e-line' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'e-lan'".format(len(ic
), ic
['name']),
627 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
628 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
629 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
631 #For each VNFC, we add it to the VNFCDict and we create a flavor.
632 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
633 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
635 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
636 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
638 VNFCitem
["name"] = vnfc
['name']
639 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
641 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
644 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
645 myflavorDict
["description"] = VNFCitem
["description"]
646 myflavorDict
["ram"] = vnfc
.get("ram", 0)
647 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
648 myflavorDict
["disk"] = vnfc
.get("disk", 1)
649 myflavorDict
["extended"] = {}
651 devices
= vnfc
.get("devices")
653 myflavorDict
["extended"]["devices"] = devices
656 # 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
657 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
659 # Previous code has been commented
660 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
661 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
662 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
663 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
665 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
667 # print "Error creating flavor: unknown processor model. Rollback successful."
668 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
670 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
671 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
673 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
674 myflavorDict
['extended']['numas'] = vnfc
['numas']
678 # Step 6.2 New flavors are created in the VIM
679 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
681 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
682 VNFCitem
["flavor_id"] = flavor_id
683 VNFCDict
[vnfc
['name']] = VNFCitem
685 logger
.debug("Creating new images in the VIM for each VNFC")
686 # Step 6.3 New images are created in the VIM
687 #For each VNFC, we must create the appropriate image.
688 #This "for" loop might be integrated with the previous one
689 #In case this integration is made, the VNFCDict might become a VNFClist.
690 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
691 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
693 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
694 image_dict
['universal_name']=vnfc
.get('image name')
695 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
696 image_dict
['location']=vnfc
.get('VNFC image')
697 image_dict
['checksum']=vnfc
.get('image checksum')
698 image_metadata_dict
= vnfc
.get('image metadata', None)
699 image_metadata_str
= None
700 if image_metadata_dict
is not None:
701 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
702 image_dict
['metadata']=image_metadata_str
703 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
704 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
705 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
706 VNFCDict
[vnfc
['name']]["image_id"] = image_id
707 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
710 # Step 7. Storing the VNF descriptor in the repository
711 if "descriptor" not in vnf_descriptor
["vnf"]:
712 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
714 # Step 8. Adding the VNF to the NFVO DB
715 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
717 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
718 _
, message
= rollback(mydb
, vims
, rollback_list
)
719 if isinstance(e
, db_base_Exception
):
720 error_text
= "Exception at database"
721 elif isinstance(e
, KeyError):
722 error_text
= "KeyError exception "
723 e
.http_code
= HTTP_Internal_Server_Error
725 error_text
= "Exception at VIM"
726 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
727 #logger.error("start_scenario %s", error_text)
728 raise NfvoException(error_text
, e
.http_code
)
730 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
731 #check valid tenant_id
732 check_tenant(mydb
, tenant_id
)
735 if tenant_id
!= "any":
736 where_or
["tenant_id"] = tenant_id
737 where_or
["public"] = True
738 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
741 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
742 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
743 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
744 data
={'vnf' : filtered_content
}
746 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
747 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description'),
748 WHERE
={'vnfs.uuid': vnf_id
} )
750 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
752 data
['vnf']['VNFC'] = content
753 #TODO: GET all the information from a VNFC and include it in the output.
756 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
757 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
758 WHERE
={'vnfs.uuid': vnf_id
} )
759 data
['vnf']['nets'] = content
761 #GET ip-profile for each net
762 for net
in data
['vnf']['nets']:
763 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
764 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
765 WHERE
={'net_id': net
["uuid"]} )
766 if len(ipprofiles
)==1:
767 net
["ip_profile"] = ipprofiles
[0]
768 elif len(ipprofiles
)>1:
769 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
772 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
774 #GET External Interfaces
775 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
776 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
777 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
778 WHERE
={'vnfs.uuid': vnf_id
},
779 WHERE_NOT
={'interfaces.external_name': None} )
781 data
['vnf']['external-connections'] = content
786 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
788 if tenant_id
!= "any":
789 check_tenant(mydb
, tenant_id
)
790 # Get the URL of the VIM from the nfvo_tenant and the datacenter
791 vims
= get_vim(mydb
, tenant_id
)
795 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
797 if tenant_id
!= "any":
798 where_or
["tenant_id"] = tenant_id
799 where_or
["public"] = True
800 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
803 # "Getting the list of flavors and tenants of the VNF"
804 flavorList
= get_flavorlist(mydb
, vnf_id
)
805 if len(flavorList
)==0:
806 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
808 imageList
= get_imagelist(mydb
, vnf_id
)
809 if len(imageList
)==0:
810 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
812 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
814 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
817 for flavor
in flavorList
:
818 #check if flavor is used by other vnf
820 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
822 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
824 #flavor not used, must be deleted
826 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
828 if flavor_vim
["datacenter_id"] not in vims
:
830 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
832 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
834 myvim
.delete_flavor(flavor_vim
["vim_id"])
835 except vimconn
.vimconnNotFoundException
as e
:
836 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
837 except vimconn
.vimconnException
as e
:
838 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
839 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
840 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
841 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
842 mydb
.delete_row_by_id('flavors', flavor
)
843 except db_base_Exception
as e
:
844 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
845 undeletedItems
.append("flavor %s" % flavor
)
848 for image
in imageList
:
850 #check if image is used by other vnf
851 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
853 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
855 #image not used, must be deleted
857 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
859 if image_vim
["datacenter_id"] not in vims
:
861 if image_vim
['created']=='false': #skip this image because not created by openmano
863 myvim
=vims
[ image_vim
["datacenter_id"] ]
865 myvim
.delete_image(image_vim
["vim_id"])
866 except vimconn
.vimconnNotFoundException
as e
:
867 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
868 except vimconn
.vimconnException
as e
:
869 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
870 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
871 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
872 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
873 mydb
.delete_row_by_id('images', image
)
874 except db_base_Exception
as e
:
875 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
876 undeletedItems
.append("image %s" % image
)
878 return vnf_id
+ " " + vnf
["name"]
880 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
882 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
883 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
887 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
888 myvim
= vims
.values()[0]
889 result
,servers
= myvim
.get_hosts_info()
891 return result
, servers
892 topology
= {'name':myvim
['name'] , 'servers': servers
}
893 return result
, topology
895 def get_hosts(mydb
, nfvo_tenant_id
):
896 vims
= get_vim(mydb
, nfvo_tenant_id
)
898 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
900 #print "nfvo.datacenter_action() error. Several datacenters found"
901 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
902 myvim
= vims
.values()[0]
904 hosts
= myvim
.get_hosts()
905 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
907 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
909 server
={'name':host
['name'], 'vms':[]}
910 for vm
in host
['instances']:
911 #get internal name and model
913 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
914 WHERE
={'vim_vm_id':vm
['id']} )
916 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
918 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
920 except db_base_Exception
as e
:
921 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
922 datacenter
['Datacenters'][0]['servers'].append(server
)
923 #return -400, "en construccion"
925 #print 'datacenters '+ json.dumps(datacenter, indent=4)
927 except vimconn
.vimconnException
as e
:
928 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
930 def new_scenario(mydb
, tenant_id
, topo
):
932 # result, vims = get_vim(mydb, tenant_id)
934 # return result, vims
936 if tenant_id
!= "any":
937 check_tenant(mydb
, tenant_id
)
938 if "tenant_id" in topo
:
939 if topo
["tenant_id"] != tenant_id
:
940 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
945 #1.1: get VNFs and external_networks (other_nets).
947 other_nets
={} #external_networks, bridge_networks and data_networkds
948 nodes
= topo
['topology']['nodes']
949 for k
in nodes
.keys():
950 if nodes
[k
]['type'] == 'VNF':
952 vnfs
[k
]['ifaces'] = {}
953 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
954 other_nets
[k
] = nodes
[k
]
955 other_nets
[k
]['external']=True
956 elif nodes
[k
]['type'] == 'network':
957 other_nets
[k
] = nodes
[k
]
958 other_nets
[k
]['external']=False
961 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
962 for name
,vnf
in vnfs
.items():
964 where_or
={"tenant_id": tenant_id
, 'public': "true"}
966 error_pos
= "'topology':'nodes':'" + name
+ "'"
968 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
969 where
['uuid'] = vnf
['vnf_id']
970 if 'VNF model' in vnf
:
971 error_text
+= " 'VNF model' " + vnf
['VNF model']
972 where
['name'] = vnf
['VNF model']
974 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
976 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
982 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
984 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
985 vnf
['uuid']=vnf_db
[0]['uuid']
986 vnf
['description']=vnf_db
[0]['description']
987 #get external interfaces
988 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
989 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
990 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
991 for ext_iface
in ext_ifaces
:
992 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
994 #1.4 get list of connections
995 conections
= topo
['topology']['connections']
997 conections_list_name
= []
998 for k
in conections
.keys():
999 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1000 ifaces_list
= conections
[k
]['nodes'].items()
1001 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1003 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1004 for k2
in conection_pair_list
:
1007 con_type
= conections
[k
].get("type", "link")
1008 if con_type
!= "link":
1010 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1011 other_nets
[k
] = {'external': False}
1012 if conections
[k
].get("graph"):
1013 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1014 ifaces_list
.append( (k
, None) )
1017 if con_type
== "external_network":
1018 other_nets
[k
]['external'] = True
1019 if conections
[k
].get("model"):
1020 other_nets
[k
]["model"] = conections
[k
]["model"]
1022 other_nets
[k
]["model"] = k
1023 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1024 other_nets
[k
]["model"] = con_type
1026 conections_list_name
.append(k
)
1027 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)
1028 #print set(ifaces_list)
1029 #check valid VNF and iface names
1030 for iface
in ifaces_list
:
1031 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1032 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1033 str(k
), iface
[0]), HTTP_Not_Found
)
1034 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1035 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1036 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1038 #1.5 unify connections from the pair list to a consolidated list
1040 while index
< len(conections_list
):
1042 while index2
< len(conections_list
):
1043 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1044 conections_list
[index
] |
= conections_list
[index2
]
1045 del conections_list
[index2
]
1046 del conections_list_name
[index2
]
1049 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1051 #for k in conections_list:
1056 #1.6 Delete non external nets
1057 # for k in other_nets.keys():
1058 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1059 # for con in conections_list:
1061 # for index in range(0,len(con)):
1062 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1063 # for index in delete_indexes:
1066 #1.7: Check external_ports are present at database table datacenter_nets
1067 for k
,net
in other_nets
.items():
1068 error_pos
= "'topology':'nodes':'" + k
+ "'"
1069 if net
['external']==False:
1070 if 'name' not in net
:
1072 if 'model' not in net
:
1073 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1074 if net
['model']=='bridge_net':
1075 net
['type']='bridge';
1076 elif net
['model']=='dataplane_net':
1079 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1081 #IF we do not want to check that external network exist at datacenter
1086 # if 'net_id' in net:
1087 # error_text += " 'net_id' " + net['net_id']
1088 # WHERE_['uuid'] = net['net_id']
1089 # if 'model' in net:
1090 # error_text += " 'model' " + net['model']
1091 # WHERE_['name'] = net['model']
1092 # if len(WHERE_) == 0:
1093 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1094 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1095 # FROM='datacenter_nets', WHERE=WHERE_ )
1097 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1099 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1100 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1102 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1103 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1104 # other_nets[k].update(net_db[0])
1107 net_nb
=0 #Number of nets
1108 for con
in conections_list
:
1109 #check if this is connected to a external net
1113 for index
in range(0,len(con
)):
1114 #check if this is connected to a external net
1115 for net_key
in other_nets
.keys():
1116 if con
[index
][0]==net_key
:
1117 if other_net_index
>=0:
1118 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1119 #print "nfvo.new_scenario " + error_text
1120 raise NfvoException(error_text
, HTTP_Bad_Request
)
1122 other_net_index
= index
1123 net_target
= net_key
1125 #print "other_net_index", other_net_index
1127 if other_net_index
>=0:
1128 del con
[other_net_index
]
1129 #IF we do not want to check that external network exist at datacenter
1130 if other_nets
[net_target
]['external'] :
1131 if "name" not in other_nets
[net_target
]:
1132 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1133 if other_nets
[net_target
]["type"] == "external_network":
1134 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1135 other_nets
[net_target
]["type"] = "data"
1137 other_nets
[net_target
]["type"] = "bridge"
1139 # if other_nets[net_target]['external'] :
1140 # 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
1141 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1142 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1143 # print "nfvo.new_scenario " + error_text
1144 # return -HTTP_Bad_Request, error_text
1147 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1150 net_type_bridge
=False
1152 net_target
= "__-__net"+str(net_nb
)
1153 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1154 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1157 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1158 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1159 if iface_type
=='mgmt' or iface_type
=='bridge':
1160 net_type_bridge
= True
1162 net_type_data
= True
1163 if net_type_bridge
and net_type_data
:
1164 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1165 #print "nfvo.new_scenario " + error_text
1166 raise NfvoException(error_text
, HTTP_Bad_Request
)
1167 elif net_type_bridge
:
1170 type_
='data' if len(con
)>2 else 'ptp'
1171 net_list
[net_target
]['type'] = type_
1174 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1175 #print "nfvo.new_scenario " + error_text
1177 raise NfvoException(error_text
, HTTP_Bad_Request
)
1179 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1180 #1.8.1 obtain management net
1181 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1182 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1183 #1.8.2 check all interfaces from all vnfs
1185 add_mgmt_net
= False
1186 for vnf
in vnfs
.values():
1187 for iface
in vnf
['ifaces'].values():
1188 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1189 #iface not connected
1190 iface
['net_key'] = 'mgmt'
1192 if add_mgmt_net
and 'mgmt' not in net_list
:
1193 net_list
['mgmt']=mgmt_net
[0]
1194 net_list
['mgmt']['external']=True
1195 net_list
['mgmt']['graph']={'visible':False}
1197 net_list
.update(other_nets
)
1199 #print 'net_list', net_list
1204 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1205 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1206 'tenant_id':tenant_id
, 'name':topo
['name'],
1207 'description':topo
.get('description',topo
['name']),
1208 'public': topo
.get('public', False)
1213 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
):
1214 scenario
= scenario_dict
["scenario"]
1215 if tenant_id
!= "any":
1216 check_tenant(mydb
, tenant_id
)
1217 if "tenant_id" in scenario
:
1218 if scenario
["tenant_id"] != tenant_id
:
1219 print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1220 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1221 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1225 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1226 for name
,vnf
in scenario
["vnfs"].iteritems():
1228 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1230 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1232 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1233 where
['uuid'] = vnf
['vnf_id']
1234 if 'vnf_name' in vnf
:
1235 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1236 where
['name'] = vnf
['vnf_name']
1238 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1239 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1245 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1247 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1248 vnf
['uuid']=vnf_db
[0]['uuid']
1249 vnf
['description']=vnf_db
[0]['description']
1251 #get external interfaces
1252 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1253 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1254 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1255 for ext_iface
in ext_ifaces
:
1256 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1258 #2: Insert net_key at every vnf interface
1259 for net_name
,net
in scenario
["networks"].iteritems():
1260 net_type_bridge
=False
1262 for iface_dict
in net
["interfaces"]:
1263 for vnf
,iface
in iface_dict
.iteritems():
1264 if vnf
not in scenario
["vnfs"]:
1265 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1266 #print "nfvo.new_scenario_v02 " + error_text
1267 raise NfvoException(error_text
, HTTP_Not_Found
)
1268 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1269 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1270 #print "nfvo.new_scenario_v02 " + error_text
1271 raise NfvoException(error_text
, HTTP_Bad_Request
)
1272 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1273 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1274 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1275 #print "nfvo.new_scenario_v02 " + error_text
1276 raise NfvoException(error_text
, HTTP_Bad_Request
)
1277 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1278 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1279 if iface_type
=='mgmt' or iface_type
=='bridge':
1280 net_type_bridge
= True
1282 net_type_data
= True
1283 if net_type_bridge
and net_type_data
:
1284 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1285 #print "nfvo.new_scenario " + error_text
1286 raise NfvoException(error_text
, HTTP_Bad_Request
)
1287 elif net_type_bridge
:
1290 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1292 net
['name'] = net_name
1293 net
['external'] = net
.get('external', False)
1295 #3: insert at database
1296 scenario
["nets"] = scenario
["networks"]
1297 scenario
['tenant_id'] = tenant_id
1298 scenario_id
= mydb
.new_scenario( scenario
)
1301 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1302 data
["uuid"] = scenario_id
1303 data
["tenant_id"] = tenant_id
1304 c
= mydb
.edit_scenario( data
)
1307 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1308 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1309 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
1310 vims
= {datacenter_id
: myvim
}
1311 myvim_tenant
= myvim
['tenant_id']
1312 datacenter_name
= myvim
['name']
1316 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1317 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1318 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
1319 scenarioDict
['datacenter_id'] = datacenter_id
1320 #print '================scenarioDict======================='
1321 #print json.dumps(scenarioDict, indent=4)
1322 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1324 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1325 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1327 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1328 auxNetDict
['scenario'] = {}
1330 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1331 for sce_net
in scenarioDict
['nets']:
1332 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1334 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1335 myNetName
= myNetName
[0:255] #limit length
1336 myNetType
= sce_net
['type']
1338 myNetDict
["name"] = myNetName
1339 myNetDict
["type"] = myNetType
1340 myNetDict
["tenant_id"] = myvim_tenant
1341 myNetIPProfile
= sce_net
.get('ip_profile', None)
1343 #We should use the dictionary as input parameter for new_network
1345 if not sce_net
["external"]:
1346 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1347 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1348 sce_net
['vim_id'] = network_id
1349 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1350 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1351 sce_net
["created"] = True
1353 if sce_net
['vim_id'] == None:
1354 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1355 _
, message
= rollback(mydb
, vims
, rollbackList
)
1356 logger
.error("nfvo.start_scenario: %s", error_text
)
1357 raise NfvoException(error_text
, HTTP_Bad_Request
)
1358 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1359 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1361 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1362 #For each vnf net, we create it and we add it to instanceNetlist.
1363 for sce_vnf
in scenarioDict
['vnfs']:
1364 for net
in sce_vnf
['nets']:
1365 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1367 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1368 myNetName
= myNetName
[0:255] #limit length
1369 myNetType
= net
['type']
1371 myNetDict
["name"] = myNetName
1372 myNetDict
["type"] = myNetType
1373 myNetDict
["tenant_id"] = myvim_tenant
1374 myNetIPProfile
= net
.get('ip_profile', None)
1377 #We should use the dictionary as input parameter for new_network
1378 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1379 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1380 net
['vim_id'] = network_id
1381 if sce_vnf
['uuid'] not in auxNetDict
:
1382 auxNetDict
[sce_vnf
['uuid']] = {}
1383 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1384 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1385 net
["created"] = True
1387 #print "auxNetDict:"
1388 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1390 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1391 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1393 for sce_vnf
in scenarioDict
['vnfs']:
1394 for vm
in sce_vnf
['vms']:
1397 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1398 myVMDict
['name'] = "%s.%s.%d" % (instance_scenario_name
,sce_vnf
['name'],i
)
1399 #myVMDict['description'] = vm['description']
1400 myVMDict
['description'] = myVMDict
['name'][0:99]
1402 myVMDict
['start'] = "no"
1403 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1404 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1406 #create image at vim in case it not exist
1407 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1408 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1409 vm
['vim_image_id'] = image_id
1411 #create flavor at vim in case it not exist
1412 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1413 if flavor_dict
['extended']!=None:
1414 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1415 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1416 vm
['vim_flavor_id'] = flavor_id
1419 myVMDict
['imageRef'] = vm
['vim_image_id']
1420 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1421 myVMDict
['networks'] = []
1422 for iface
in vm
['interfaces']:
1424 if iface
['type']=="data":
1425 netDict
['type'] = iface
['model']
1426 elif "model" in iface
and iface
["model"]!=None:
1427 netDict
['model']=iface
['model']
1428 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1429 #discover type of interface looking at flavor
1430 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1431 for flavor_iface
in numa
.get('interfaces',[]):
1432 if flavor_iface
.get('name') == iface
['internal_name']:
1433 if flavor_iface
['dedicated'] == 'yes':
1434 netDict
['type']="PF" #passthrough
1435 elif flavor_iface
['dedicated'] == 'no':
1436 netDict
['type']="VF" #siov
1437 elif flavor_iface
['dedicated'] == 'yes:sriov':
1438 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1439 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1441 netDict
["use"]=iface
['type']
1442 if netDict
["use"]=="data" and not netDict
.get("type"):
1443 #print "netDict", netDict
1444 #print "iface", iface
1445 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'])
1446 if flavor_dict
.get('extended')==None:
1447 raise NfvoException(e_text
+ "After database migration some information is not available. \
1448 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1450 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1451 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1452 netDict
["type"]="virtual"
1453 if "vpci" in iface
and iface
["vpci"] is not None:
1454 netDict
['vpci'] = iface
['vpci']
1455 if "mac" in iface
and iface
["mac"] is not None:
1456 netDict
['mac_address'] = iface
['mac']
1457 netDict
['name'] = iface
['internal_name']
1458 if iface
['net_id'] is None:
1459 for vnf_iface
in sce_vnf
["interfaces"]:
1462 if vnf_iface
['interface_id']==iface
['uuid']:
1463 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1466 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1467 #skip bridge ifaces not connected to any net
1468 #if 'net_id' not in netDict or netDict['net_id']==None:
1470 myVMDict
['networks'].append(netDict
)
1471 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1472 #print myVMDict['name']
1473 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1474 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1475 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1476 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1477 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1478 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1479 vm
['vim_id'] = vm_id
1480 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1481 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1482 for net
in myVMDict
['networks']:
1484 for iface
in vm
['interfaces']:
1485 if net
["name"]==iface
["internal_name"]:
1486 iface
["vim_id"]=net
["vim_id"]
1489 logger
.debug("start scenario Deployment done")
1490 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1491 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1492 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1493 return mydb
.get_instance_scenario(instance_id
)
1495 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1496 _
, message
= rollback(mydb
, vims
, rollbackList
)
1497 if isinstance(e
, db_base_Exception
):
1498 error_text
= "Exception at database"
1500 error_text
= "Exception at VIM"
1501 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1502 #logger.error("start_scenario %s", error_text)
1503 raise NfvoException(error_text
, e
.http_code
)
1505 def unify_cloud_config(cloud_config
):
1506 index_to_delete
= []
1507 users
= cloud_config
.get("users", [])
1508 for index0
in range(0,len(users
)):
1509 if index0
in index_to_delete
:
1511 for index1
in range(index0
+1,len(users
)):
1512 if index1
in index_to_delete
:
1514 if users
[index0
]["name"] == users
[index1
]["name"]:
1515 index_to_delete
.append(index1
)
1516 for key
in users
[index1
].get("key-pairs",()):
1517 if "key-pairs" not in users
[index0
]:
1518 users
[index0
]["key-pairs"] = [key
]
1519 elif key
not in users
[index0
]["key-pairs"]:
1520 users
[index0
]["key-pairs"].append(key
)
1521 index_to_delete
.sort(reverse
=True)
1522 for index
in index_to_delete
:
1525 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1526 datacenter_id
= None
1527 datacenter_name
= None
1528 if datacenter_id_name
:
1529 if utils
.check_valid_uuid(datacenter_id_name
):
1530 datacenter_id
= datacenter_id_name
1532 datacenter_name
= datacenter_id_name
1533 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1535 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1537 #print "nfvo.datacenter_action() error. Several datacenters found"
1538 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1539 return vims
.keys()[0], vims
.values()[0]
1541 def new_scenario_v03(mydb
, tenant_id
, scenario_dict
):
1542 scenario
= scenario_dict
["scenario"]
1543 if tenant_id
!= "any":
1544 check_tenant(mydb
, tenant_id
)
1545 if "tenant_id" in scenario
:
1546 if scenario
["tenant_id"] != tenant_id
:
1547 logger("Tenant '%s' not found", tenant_id
)
1548 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1549 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1553 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1554 for name
,vnf
in scenario
["vnfs"].iteritems():
1556 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1558 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1560 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1561 where
['uuid'] = vnf
['vnf_id']
1562 if 'vnf_name' in vnf
:
1563 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1564 where
['name'] = vnf
['vnf_name']
1566 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1567 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1573 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1575 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1576 vnf
['uuid']=vnf_db
[0]['uuid']
1577 vnf
['description']=vnf_db
[0]['description']
1579 # get external interfaces
1580 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1581 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1582 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1583 for ext_iface
in ext_ifaces
:
1584 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1586 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1588 #2: Insert net_key and ip_address at every vnf interface
1589 for net_name
,net
in scenario
["networks"].iteritems():
1590 net_type_bridge
=False
1592 for iface_dict
in net
["interfaces"]:
1593 logger
.debug("Iface_dict %s", iface_dict
)
1594 vnf
= iface_dict
["vnf"]
1595 iface
= iface_dict
["vnf_interface"]
1596 if vnf
not in scenario
["vnfs"]:
1597 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1598 #logger.debug(error_text)
1599 raise NfvoException(error_text
, HTTP_Not_Found
)
1600 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1601 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1602 #logger.debug(error_text)
1603 raise NfvoException(error_text
, HTTP_Bad_Request
)
1604 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1605 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1606 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1607 #logger.debug(error_text)
1608 raise NfvoException(error_text
, HTTP_Bad_Request
)
1609 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1610 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['ip_address'] = iface_dict
.get('ip_address',None)
1611 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1612 if iface_type
=='mgmt' or iface_type
=='bridge':
1613 net_type_bridge
= True
1615 net_type_data
= True
1616 if net_type_bridge
and net_type_data
:
1617 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1618 #logger.debug(error_text)
1619 raise NfvoException(error_text
, HTTP_Bad_Request
)
1620 elif net_type_bridge
:
1623 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1625 if ("implementation" in net
):
1626 if (type_
== "bridge" and net
["implementation"] == "underlay"):
1627 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at 'network':'%s'" % (net_name
)
1628 #logger.debug(error_text)
1629 raise NfvoException(error_text
, HTTP_Bad_Request
)
1630 elif (type_
<> "bridge" and net
["implementation"] == "overlay"):
1631 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at 'network':'%s'" % (net_name
)
1632 #logger.debug(error_text)
1633 raise NfvoException(error_text
, HTTP_Bad_Request
)
1634 net
.pop("implementation")
1636 if (type_
== "data" and net
["type"] == "e-line"):
1637 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type 'e-line' at 'network':'%s'" % (net_name
)
1638 #logger.debug(error_text)
1639 raise NfvoException(error_text
, HTTP_Bad_Request
)
1640 elif (type_
== "ptp" and net
["type"] == "e-lan"):
1644 net
['name'] = net_name
1645 net
['external'] = net
.get('external', False)
1647 #3: insert at database
1648 scenario
["nets"] = scenario
["networks"]
1649 scenario
['tenant_id'] = tenant_id
1650 scenario_id
= mydb
.new_scenario2(scenario
)
1654 '''Takes dict d and updates it with the values in dict u.'''
1655 '''It merges all depth levels'''
1656 for k
, v
in u
.iteritems():
1657 if isinstance(v
, collections
.Mapping
):
1658 r
= update(d
.get(k
, {}), v
)
1664 def create_instance(mydb
, tenant_id
, instance_dict
):
1665 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1666 #logger.debug("Creating instance...")
1667 scenario
= instance_dict
["scenario"]
1669 #find main datacenter
1671 datacenter2tenant
= {}
1672 datacenter
= instance_dict
.get("datacenter")
1673 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1674 myvims
[default_datacenter_id
] = vim
1675 datacenter2tenant
[default_datacenter_id
] = vim
['config']['datacenter_tenant_id']
1676 #myvim_tenant = myvim['tenant_id']
1677 # default_datacenter_name = vim['name']
1680 #print "Checking that the scenario exists and getting the scenario dictionary"
1681 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1683 #logger.debug(">>>>>>> Dictionaries before merging")
1684 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1685 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1687 scenarioDict
['datacenter_id'] = default_datacenter_id
1689 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1690 auxNetDict
['scenario'] = {}
1692 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1693 instance_name
= instance_dict
["name"]
1694 instance_description
= instance_dict
.get("description")
1696 #0 check correct parameters
1697 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1699 for scenario_net
in scenarioDict
['nets']:
1700 if net_name
== scenario_net
["name"]:
1704 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1705 if "sites" not in net_instance_desc
:
1706 net_instance_desc
["sites"] = [ {} ]
1707 site_without_datacenter_field
= False
1708 for site
in net_instance_desc
["sites"]:
1709 if site
.get("datacenter"):
1710 if site
["datacenter"] not in myvims
:
1711 #Add this datacenter to myvims
1712 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1714 datacenter2tenant
[d
] = v
['config']['datacenter_tenant_id']
1715 site
["datacenter"] = d
#change name to id
1717 if site_without_datacenter_field
:
1718 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1719 site_without_datacenter_field
= True
1720 site
["datacenter"] = default_datacenter_id
#change name to id
1722 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
1724 for scenario_vnf
in scenarioDict
['vnfs']:
1725 if vnf_name
== scenario_vnf
['name']:
1729 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
1730 if "datacenter" in vnf_instance_desc
:
1731 #Add this datacenter to myvims
1732 if vnf_instance_desc
["datacenter"] not in myvims
:
1733 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
1735 datacenter2tenant
[d
] = v
['config']['datacenter_tenant_id']
1736 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
1737 #0.1 parse cloud-config parameters
1738 cloud_config
= scenarioDict
.get("cloud-config", {})
1739 if instance_dict
.get("cloud-config"):
1740 cloud_config
.update( instance_dict
["cloud-config"])
1741 if not cloud_config
:
1744 scenarioDict
["cloud-config"] = cloud_config
1745 unify_cloud_config(cloud_config
)
1747 #0.2 merge instance information into scenario
1748 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
1749 #However, this is not possible yet.
1750 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1751 for scenario_net
in scenarioDict
['nets']:
1752 if net_name
== scenario_net
["name"]:
1753 if 'ip-profile' in net_instance_desc
:
1754 ipprofile
= net_instance_desc
['ip-profile']
1755 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
1756 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
1757 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
1758 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
1759 if 'dhcp' in ipprofile
:
1760 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
1761 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
1762 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
1763 del ipprofile
['dhcp']
1764 if 'ip_profile' not in scenario_net
:
1765 scenario_net
['ip_profile'] = ipprofile
1767 update(scenario_net
['ip_profile'],ipprofile
)
1768 for interface
in net_instance_desc
.get('interfaces', () ):
1769 if 'ip_address' in interface
:
1770 for vnf
in scenarioDict
['vnfs']:
1771 if interface
['vnf'] == vnf
['name']:
1772 for vnf_interface
in vnf
['interfaces']:
1773 if interface
['vnf_interface'] == vnf_interface
['external_name']:
1774 vnf_interface
['ip_address']=interface
['ip_address']
1776 #logger.debug(">>>>>>>> Merged dictionary")
1777 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
1780 #1. Creating new nets (sce_nets) in the VIM"
1781 for sce_net
in scenarioDict
['nets']:
1782 sce_net
["vim_id_sites"]={}
1783 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
1784 net_name
= descriptor_net
.get("vim-network-name")
1785 auxNetDict
['scenario'][sce_net
['uuid']] = {}
1787 sites
= descriptor_net
.get("sites", [ {} ])
1789 if site
.get("datacenter"):
1790 vim
= myvims
[ site
["datacenter"] ]
1791 datacenter_id
= site
["datacenter"]
1793 vim
= myvims
[ default_datacenter_id
]
1794 datacenter_id
= default_datacenter_id
1795 net_type
= sce_net
['type']
1796 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
1797 if sce_net
["external"]:
1799 net_name
= sce_net
["name"]
1800 if "netmap-use" in site
or "netmap-create" in site
:
1801 create_network
= False
1802 lookfor_network
= False
1803 if "netmap-use" in site
:
1804 lookfor_network
= True
1805 if utils
.check_valid_uuid(site
["netmap-use"]):
1806 filter_text
= "scenario id '%s'" % site
["netmap-use"]
1807 lookfor_filter
["id"] = site
["netmap-use"]
1809 filter_text
= "scenario name '%s'" % site
["netmap-use"]
1810 lookfor_filter
["name"] = site
["netmap-use"]
1811 if "netmap-create" in site
:
1812 create_network
= True
1813 net_vim_name
= net_name
1814 if site
["netmap-create"]:
1815 net_vim_name
= site
["netmap-create"]
1817 elif sce_net
['vim_id'] != None:
1818 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
1819 create_network
= False
1820 lookfor_network
= True
1821 lookfor_filter
["id"] = sce_net
['vim_id']
1822 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
1823 #look for network at datacenter and return error
1825 #There is not a netmap, look at datacenter for a net with this name and create if not found
1826 create_network
= True
1827 lookfor_network
= True
1828 lookfor_filter
["name"] = sce_net
["name"]
1829 net_vim_name
= sce_net
["name"]
1830 filter_text
= "scenario name '%s'" % sce_net
["name"]
1833 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
1834 net_name
= net_name
[:255] #limit length
1835 net_vim_name
= net_name
1836 create_network
= True
1837 lookfor_network
= False
1840 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
1841 if len(vim_nets
) > 1:
1842 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1843 elif len(vim_nets
) == 0:
1844 if not create_network
:
1845 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1847 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
1848 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
1849 create_network
= False
1851 #if network is not external
1852 network_id
= vim
.new_network(net_vim_name
, net_type
, sce_net
.get('ip_profile',None))
1853 sce_net
["vim_id_sites"][datacenter_id
] = network_id
1854 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = network_id
1855 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':network_id
})
1856 sce_net
["created"] = True
1858 #2. Creating new nets (vnf internal nets) in the VIM"
1859 #For each vnf net, we create it and we add it to instanceNetlist.
1860 for sce_vnf
in scenarioDict
['vnfs']:
1861 for net
in sce_vnf
['nets']:
1862 if sce_vnf
.get("datacenter"):
1863 vim
= myvims
[ sce_vnf
["datacenter"] ]
1864 datacenter_id
= sce_vnf
["datacenter"]
1866 vim
= myvims
[ default_datacenter_id
]
1867 datacenter_id
= default_datacenter_id
1868 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
1869 net_name
= descriptor_net
.get("name")
1871 net_name
= "%s.%s" %(instance_name
, net
["name"])
1872 net_name
= net_name
[:255] #limit length
1873 net_type
= net
['type']
1874 network_id
= vim
.new_network(net_name
, net_type
, net
.get('ip_profile',None))
1875 net
['vim_id'] = network_id
1876 if sce_vnf
['uuid'] not in auxNetDict
:
1877 auxNetDict
[sce_vnf
['uuid']] = {}
1878 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1879 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1880 net
["created"] = True
1883 #print "auxNetDict:"
1884 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1886 #3. Creating new vm instances in the VIM
1887 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1888 for sce_vnf
in scenarioDict
['vnfs']:
1889 if sce_vnf
.get("datacenter"):
1890 vim
= myvims
[ sce_vnf
["datacenter"] ]
1891 datacenter_id
= sce_vnf
["datacenter"]
1893 vim
= myvims
[ default_datacenter_id
]
1894 datacenter_id
= default_datacenter_id
1895 sce_vnf
["datacenter_id"] = datacenter_id
1897 for vm
in sce_vnf
['vms']:
1900 myVMDict
['name'] = "%s.%s.%d" % (instance_name
,sce_vnf
['name'],i
)
1901 myVMDict
['description'] = myVMDict
['name'][0:99]
1903 # myVMDict['start'] = "no"
1904 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1905 #create image at vim in case it not exist
1906 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1907 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
1908 vm
['vim_image_id'] = image_id
1910 #create flavor at vim in case it not exist
1911 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1912 if flavor_dict
['extended']!=None:
1913 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1914 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
1915 vm
['vim_flavor_id'] = flavor_id
1917 myVMDict
['imageRef'] = vm
['vim_image_id']
1918 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1919 myVMDict
['networks'] = []
1920 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
1921 for iface
in vm
['interfaces']:
1923 if iface
['type']=="data":
1924 netDict
['type'] = iface
['model']
1925 elif "model" in iface
and iface
["model"]!=None:
1926 netDict
['model']=iface
['model']
1927 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1928 #discover type of interface looking at flavor
1929 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1930 for flavor_iface
in numa
.get('interfaces',[]):
1931 if flavor_iface
.get('name') == iface
['internal_name']:
1932 if flavor_iface
['dedicated'] == 'yes':
1933 netDict
['type']="PF" #passthrough
1934 elif flavor_iface
['dedicated'] == 'no':
1935 netDict
['type']="VF" #siov
1936 elif flavor_iface
['dedicated'] == 'yes:sriov':
1937 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1938 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1940 netDict
["use"]=iface
['type']
1941 if netDict
["use"]=="data" and not netDict
.get("type"):
1942 #print "netDict", netDict
1943 #print "iface", iface
1944 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'])
1945 if flavor_dict
.get('extended')==None:
1946 raise NfvoException(e_text
+ "After database migration some information is not available. \
1947 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1949 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1950 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1951 netDict
["type"]="virtual"
1952 if "vpci" in iface
and iface
["vpci"] is not None:
1953 netDict
['vpci'] = iface
['vpci']
1954 if "mac" in iface
and iface
["mac"] is not None:
1955 netDict
['mac_address'] = iface
['mac']
1956 netDict
['name'] = iface
['internal_name']
1957 if iface
['net_id'] is None:
1958 for vnf_iface
in sce_vnf
["interfaces"]:
1961 if vnf_iface
['interface_id']==iface
['uuid']:
1962 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
1965 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1966 #skip bridge ifaces not connected to any net
1967 #if 'net_id' not in netDict or netDict['net_id']==None:
1969 myVMDict
['networks'].append(netDict
)
1970 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1971 #print myVMDict['name']
1972 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1973 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1974 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1975 vm_id
= vim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1976 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'], cloud_config
= cloud_config
)
1977 vm
['vim_id'] = vm_id
1978 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1979 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1980 for net
in myVMDict
['networks']:
1982 for iface
in vm
['interfaces']:
1983 if net
["name"]==iface
["internal_name"]:
1984 iface
["vim_id"]=net
["vim_id"]
1986 scenarioDict
["datacenter2tenant"] = datacenter2tenant
1987 logger
.debug("create_instance Deployment done scenarioDict: %s",
1988 yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False) )
1989 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
1990 return mydb
.get_instance_scenario(instance_id
)
1991 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
1992 message
= rollback(mydb
, myvims
, rollbackList
)
1993 if isinstance(e
, db_base_Exception
):
1994 error_text
= "database Exception"
1995 elif isinstance(e
, vimconn
.vimconnException
):
1996 error_text
= "VIM Exception"
1998 error_text
= "Exception"
1999 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2000 #logger.error("create_instance: %s", error_text)
2001 raise NfvoException(error_text
, e
.http_code
)
2003 def delete_instance(mydb
, tenant_id
, instance_id
):
2004 #print "Checking that the instance_id exists and getting the instance dictionary"
2005 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2006 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2007 tenant_id
= instanceDict
["tenant_id"]
2008 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2010 #1. Delete from Database
2011 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2019 for sce_vnf
in instanceDict
['vnfs']:
2020 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2021 if datacenter_key
not in myvims
:
2022 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2023 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2025 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2026 sce_vnf
["datacenter_tenant_id"]))
2027 myvims
[datacenter_key
] = None
2029 myvims
[datacenter_key
] = vims
.values()[0]
2030 myvim
= myvims
[datacenter_key
]
2031 for vm
in sce_vnf
['vms']:
2033 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2036 myvim
.delete_vminstance(vm
['vim_vm_id'])
2037 except vimconn
.vimconnNotFoundException
as e
:
2038 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2039 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2040 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2041 except vimconn
.vimconnException
as e
:
2042 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2043 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2044 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2048 for net
in instanceDict
['nets']:
2049 if not net
['created']:
2050 continue #skip not created nets
2051 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2052 if datacenter_key
not in myvims
:
2053 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2054 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2056 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2057 myvims
[datacenter_key
] = None
2059 myvims
[datacenter_key
] = vims
.values()[0]
2060 myvim
= myvims
[datacenter_key
]
2063 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2066 myvim
.delete_network(net
['vim_net_id'])
2067 except vimconn
.vimconnNotFoundException
as e
:
2068 error_msg
+="\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2069 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2070 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2071 except vimconn
.vimconnException
as e
:
2072 error_msg
+="\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'], net
["datacenter_id"], e
.http_code
, str(e
))
2073 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2074 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2075 if len(error_msg
)>0:
2076 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2078 return 'instance ' + message
+ ' deleted'
2080 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2081 '''Refreshes a scenario instance. It modifies instanceDict'''
2083 - 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
2086 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2087 #print "nfvo.refresh_instance begins"
2088 #print json.dumps(instanceDict, indent=4)
2090 #print "Getting the VIM URL and the VIM tenant_id"
2093 # 1. Getting VIM vm and net list
2094 vms_updated
= [] #List of VM instance uuids in openmano that were updated
2097 for sce_vnf
in instanceDict
['vnfs']:
2098 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2099 if datacenter_key
not in vm_list
:
2100 vm_list
[datacenter_key
] = []
2101 if datacenter_key
not in myvims
:
2102 vims
= get_vim(mydb
, nfvo_tenant
, datacenter_id
=sce_vnf
["datacenter_id"],
2103 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2105 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"]))
2106 myvims
[datacenter_key
] = None
2108 myvims
[datacenter_key
] = vims
.values()[0]
2109 for vm
in sce_vnf
['vms']:
2110 vm_list
[datacenter_key
].append(vm
['vim_vm_id'])
2111 vms_notupdated
.append(vm
["uuid"])
2113 nets_updated
= [] #List of VM instance uuids in openmano that were updated
2116 for net
in instanceDict
['nets']:
2117 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2118 if datacenter_key
not in net_list
:
2119 net_list
[datacenter_key
] = []
2120 if datacenter_key
not in myvims
:
2121 vims
= get_vim(mydb
, nfvo_tenant
, datacenter_id
=net
["datacenter_id"],
2122 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2124 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2125 myvims
[datacenter_key
] = None
2127 myvims
[datacenter_key
] = vims
.values()[0]
2129 net_list
[datacenter_key
].append(net
['vim_net_id'])
2130 nets_notupdated
.append(net
["uuid"])
2132 # 1. Getting the status of all VMs
2134 for datacenter_key
in myvims
:
2135 if not vm_list
.get(datacenter_key
):
2139 if not myvims
[datacenter_key
]:
2140 failed_message
= "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"])
2143 vm_dict
.update(myvims
[datacenter_key
].refresh_vms_status(vm_list
[datacenter_key
]) )
2145 except vimconn
.vimconnException
as e
:
2146 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
2147 failed_message
= str(e
)
2149 for vm
in vm_list
[datacenter_key
]:
2150 vm_dict
[vm
] = {'status': "VIM_ERROR", 'error_msg': failed_message
}
2152 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2153 for sce_vnf
in instanceDict
['vnfs']:
2154 for vm
in sce_vnf
['vms']:
2155 vm_id
= vm
['vim_vm_id']
2156 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
2157 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2158 has_mgmt_iface
= False
2159 for iface
in vm
["interfaces"]:
2160 if iface
["type"]=="mgmt":
2161 has_mgmt_iface
= True
2162 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
2163 vm_dict
[vm_id
]['status'] = "ACTIVE"
2164 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'):
2165 vm
['status'] = vm_dict
[vm_id
]['status']
2166 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
2167 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
2168 # 2.1. Update in openmano DB the VMs whose status changed
2170 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
2171 vms_notupdated
.remove(vm
["uuid"])
2173 vms_updated
.append(vm
["uuid"])
2174 except db_base_Exception
as e
:
2175 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2176 # 2.2. Update in openmano DB the interface VMs
2177 for interface
in interfaces
:
2178 #translate from vim_net_id to instance_net_id
2180 for net
in instanceDict
['nets']:
2181 if net
["vim_net_id"] == interface
["vim_net_id"]:
2182 network_id_list
.append(net
["uuid"])
2183 if not network_id_list
:
2185 del interface
["vim_net_id"]
2187 for network_id
in network_id_list
:
2188 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
2189 except db_base_Exception
as e
:
2190 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
2192 # 3. Getting the status of all nets
2194 for datacenter_key
in myvims
:
2195 if not net_list
.get(datacenter_key
):
2199 if not myvims
[datacenter_key
]:
2200 failed_message
= "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"])
2203 net_dict
.update(myvims
[datacenter_key
].refresh_nets_status(net_list
[datacenter_key
]) )
2205 except vimconn
.vimconnException
as e
:
2206 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
2207 failed_message
= str(e
)
2209 for net
in net_list
[datacenter_key
]:
2210 net_dict
[net
] = {'status': "VIM_ERROR", 'error_msg': failed_message
}
2212 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2213 # TODO: update nets inside a vnf
2214 for net
in instanceDict
['nets']:
2215 net_id
= net
['vim_net_id']
2216 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'):
2217 net
['status'] = net_dict
[net_id
]['status']
2218 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
2219 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
2220 # 5.1. Update in openmano DB the nets whose status changed
2222 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
2223 nets_notupdated
.remove(net
["uuid"])
2225 nets_updated
.append(net
["uuid"])
2226 except db_base_Exception
as e
:
2227 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2229 # Returns appropriate output
2230 #print "nfvo.refresh_instance finishes"
2231 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2232 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
2233 instance_id
= instanceDict
['uuid']
2234 if len(vms_notupdated
)+len(nets_notupdated
)>0:
2235 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
2236 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
2238 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2240 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2241 #print "Checking that the instance_id exists and getting the instance dictionary"
2242 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2243 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2245 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2246 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2248 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2249 myvim
= vims
.values()[0]
2252 input_vnfs
= action_dict
.pop("vnfs", [])
2253 input_vms
= action_dict
.pop("vms", [])
2254 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2258 for sce_vnf
in instanceDict
['vnfs']:
2259 for vm
in sce_vnf
['vms']:
2260 if not action_over_all
:
2261 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2262 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2265 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2266 if "console" in action_dict
:
2267 if not global_config
["http_console_proxy"]:
2268 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2269 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2270 protocol
=data
["protocol"],
2271 ip
= data
["server"],
2272 port
= data
["port"],
2273 suffix
= data
["suffix"]),
2277 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2278 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2279 "description": "this console is only reachable by local interface",
2284 #print "console data", data
2286 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2287 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2288 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2289 protocol
=data
["protocol"],
2290 ip
= global_config
["http_console_host"],
2291 port
= console_thread
.port
,
2292 suffix
= data
["suffix"]),
2296 except NfvoException
as e
:
2297 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2301 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2303 except vimconn
.vimconnException
as e
:
2304 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2307 if vm_ok
==0: #all goes wrong
2312 def create_or_use_console_proxy_thread(console_server
, console_port
):
2313 #look for a non-used port
2314 console_thread_key
= console_server
+ ":" + str(console_port
)
2315 if console_thread_key
in global_config
["console_thread"]:
2316 #global_config["console_thread"][console_thread_key].start_timeout()
2317 return global_config
["console_thread"][console_thread_key
]
2319 for port
in global_config
["console_port_iterator"]():
2320 #print "create_or_use_console_proxy_thread() port:", port
2321 if port
in global_config
["console_ports"]:
2324 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2326 global_config
["console_thread"][console_thread_key
] = clithread
2327 global_config
["console_ports"][port
] = console_thread_key
2329 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2330 #port used, try with onoher
2332 except cli
.ConsoleProxyException
as e
:
2333 raise NfvoException(str(e
), HTTP_Bad_Request
)
2334 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2336 def check_tenant(mydb
, tenant_id
):
2337 '''check that tenant exists at database'''
2338 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2340 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2343 def new_tenant(mydb
, tenant_dict
):
2344 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2347 def delete_tenant(mydb
, tenant
):
2348 #get nfvo_tenant info
2350 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2351 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2352 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2354 def new_datacenter(mydb
, datacenter_descriptor
):
2355 if "config" in datacenter_descriptor
:
2356 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2357 #Check that datacenter-type is correct
2358 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2361 module
= "vimconn_" + datacenter_type
2362 module_info
= imp
.find_module(module
)
2363 except (IOError, ImportError):
2364 if module_info
and module_info
[0]:
2365 file.close(module_info
[0])
2366 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2368 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2369 return datacenter_id
2371 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2372 #obtain data, check that only one exist
2373 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2375 datacenter_id
= datacenter
['uuid']
2376 where
={'uuid': datacenter
['uuid']}
2377 if "config" in datacenter_descriptor
:
2378 if datacenter_descriptor
['config']!=None:
2380 new_config_dict
= datacenter_descriptor
["config"]
2383 for k
in new_config_dict
:
2384 if new_config_dict
[k
]==None:
2387 config_dict
= yaml
.load(datacenter
["config"])
2388 config_dict
.update(new_config_dict
)
2392 except Exception as e
:
2393 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2394 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2395 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2396 return datacenter_id
2398 def delete_datacenter(mydb
, datacenter
):
2399 #get nfvo_tenant info
2400 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2401 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2402 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2404 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None):
2405 #get datacenter info
2406 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2407 datacenter_name
=myvim
["name"]
2409 create_vim_tenant
=True if vim_tenant_id
==None and vim_tenant_name
==None else False
2411 #get nfvo_tenant info
2412 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2413 if vim_tenant_name
==None:
2414 vim_tenant_name
=tenant_dict
['name']
2416 #check that this association does not exist before
2417 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2418 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2419 if len(tenants_datacenters
)>0:
2420 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2422 vim_tenant_id_exist_atdb
=False
2423 if not create_vim_tenant
:
2424 where_
={"datacenter_id": datacenter_id
}
2425 if vim_tenant_id
!=None:
2426 where_
["vim_tenant_id"] = vim_tenant_id
2427 if vim_tenant_name
!=None:
2428 where_
["vim_tenant_name"] = vim_tenant_name
2429 #check if vim_tenant_id is already at database
2430 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2431 if len(datacenter_tenants_dict
)>=1:
2432 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2433 vim_tenant_id_exist_atdb
=True
2434 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2436 datacenter_tenants_dict
= {}
2437 #insert at table datacenter_tenants
2438 else: #if vim_tenant_id==None:
2439 #create tenant at VIM if not provided
2441 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2442 except vimconn
.vimconnException
as e
:
2443 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2444 datacenter_tenants_dict
= {}
2445 datacenter_tenants_dict
["created"]="true"
2447 #fill datacenter_tenants table
2448 if not vim_tenant_id_exist_atdb
:
2449 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2450 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2451 datacenter_tenants_dict
["user"] = vim_username
2452 datacenter_tenants_dict
["passwd"] = vim_password
2453 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2454 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2455 datacenter_tenants_dict
["uuid"] = id_
2457 #fill tenants_datacenters table
2458 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2459 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2460 return datacenter_id
2462 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2463 #get datacenter info
2464 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2466 #get nfvo_tenant info
2467 if not tenant_id
or tenant_id
=="any":
2470 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2471 tenant_uuid
= tenant_dict
['uuid']
2473 #check that this association exist before
2474 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2476 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2477 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2478 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2479 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2481 #delete this association
2482 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2484 #get vim_tenant info and deletes
2486 for tenant_datacenter_item
in tenant_datacenter_list
:
2487 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2488 #try to delete vim:tenant
2490 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2491 if vim_tenant_dict
['created']=='true':
2492 #delete tenant at VIM if created by NFVO
2494 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2495 except vimconn
.vimconnException
as e
:
2496 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2497 logger
.warn(warning
)
2498 except db_base_Exception
as e
:
2499 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2500 pass #the error will be caused because dependencies, vim_tenant can not be deleted
2502 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2504 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2506 #get datacenter info
2507 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2509 if 'net-update' in action_dict
:
2511 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2513 except vimconn
.vimconnException
as e
:
2514 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2515 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2516 #update nets Change from VIM format to NFVO format
2519 net_nfvo
={'datacenter_id': datacenter_id
}
2520 net_nfvo
['name'] = net
['name']
2521 #net_nfvo['description']= net['name']
2522 net_nfvo
['vim_net_id'] = net
['id']
2523 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2524 net_nfvo
['shared'] = net
['shared']
2525 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2526 net_list
.append(net_nfvo
)
2527 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2528 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2530 elif 'net-edit' in action_dict
:
2531 net
= action_dict
['net-edit'].pop('net')
2532 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2533 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2534 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2536 elif 'net-delete' in action_dict
:
2537 net
= action_dict
['net-deelte'].get('net')
2538 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2539 result
= mydb
.delete_row(FROM
='datacenter_nets',
2540 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2544 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2546 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2547 #get datacenter info
2548 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2550 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2551 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2552 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2555 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2556 #get datacenter info
2557 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2560 action_dict
= action_dict
["netmap"]
2561 if 'vim_id' in action_dict
:
2562 filter_dict
["id"] = action_dict
['vim_id']
2563 if 'vim_name' in action_dict
:
2564 filter_dict
["name"] = action_dict
['vim_name']
2566 filter_dict
["shared"] = True
2569 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
2570 except vimconn
.vimconnException
as e
:
2571 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
2572 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2573 if len(vim_nets
)>1 and action_dict
:
2574 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
2575 elif len(vim_nets
)==0: # and action_dict:
2576 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
2578 for net
in vim_nets
:
2579 net_nfvo
={'datacenter_id': datacenter_id
}
2580 if action_dict
and "name" in action_dict
:
2581 net_nfvo
['name'] = action_dict
['name']
2583 net_nfvo
['name'] = net
['name']
2584 #net_nfvo['description']= net['name']
2585 net_nfvo
['vim_net_id'] = net
['id']
2586 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2587 net_nfvo
['shared'] = net
['shared']
2588 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2590 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2591 net_nfvo
["status"] = "OK"
2592 net_nfvo
["uuid"] = net_id
2593 except db_base_Exception
as e
:
2597 net_nfvo
["status"] = "FAIL: " + str(e
)
2598 net_list
.append(net_nfvo
)
2601 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2602 #get datacenter info
2603 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2606 if utils
.check_valid_uuid(name
):
2607 filter_dict
["id"] = name
2609 filter_dict
["name"] = name
2611 if item
=="networks":
2612 #filter_dict['tenant_id'] = myvim['tenant_id']
2613 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2614 elif item
=="tenants":
2615 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2617 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2618 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
2619 if name
and len(content
)==1:
2620 return {item
[:-1]: content
[0]}
2621 elif name
and len(content
)==0:
2622 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
2625 return {item
: content
}
2626 except vimconn
.vimconnException
as e
:
2627 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
2628 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
2630 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
2631 #get datacenter info
2632 if tenant_id
== "any":
2635 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2637 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2638 logger
.debug("vim_action_delete vim response: " + str(content
))
2639 items
= content
.values()[0]
2640 if type(items
)==list and len(items
)==0:
2641 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
2642 elif type(items
)==list and len(items
)>1:
2643 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
2644 else: # it is a dict
2645 item_id
= items
["id"]
2646 item_name
= str(items
.get("name"))
2649 if item
=="networks":
2650 content
= myvim
.delete_network(item_id
)
2651 elif item
=="tenants":
2652 content
= myvim
.delete_tenant(item_id
)
2654 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2655 except vimconn
.vimconnException
as e
:
2656 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
2657 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
2659 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
2661 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2662 #get datacenter info
2663 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
2664 if tenant_id
== "any":
2666 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2668 if item
=="networks":
2669 net
= descriptor
["network"]
2670 net_name
= net
.pop("name")
2671 net_type
= net
.pop("type", "bridge")
2672 net_public
= net
.pop("shared", False)
2673 net_ipprofile
= net
.pop("ip_profile", None)
2674 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, **net
)
2675 elif item
=="tenants":
2676 tenant
= descriptor
["tenant"]
2677 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2679 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2680 except vimconn
.vimconnException
as e
:
2681 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
2683 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)