1 # -*- coding: utf-8 -*-
4 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
5 # This file is part of openmano
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
25 NFVO engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances
27 __author__
="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
28 __date__
="$16-sep-2014 22:05:01$"
34 from db_base
import HTTP_Unauthorized
, HTTP_Bad_Request
, HTTP_Internal_Server_Error
, HTTP_Not_Found
,\
35 HTTP_Conflict
, HTTP_Method_Not_Allowed
36 import console_proxy_thread
as cli
40 from db_base
import db_base_Exception
43 global vimconn_imported
47 vimconn_imported
={} #dictionary with VIM type as key, loaded module as value
48 logger
= logging
.getLogger('openmano.nfvo')
50 class NfvoException(Exception):
51 def __init__(self
, message
, http_code
):
52 self
.http_code
= http_code
53 Exception.__init
__(self
, message
)
56 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
58 return result, content:
59 <0, error_text upon error
60 nb_records, flavor_list on success
63 WHERE_dict
['vnf_id'] = vnf_id
64 if nfvo_tenant
is not None:
65 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
67 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
68 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
69 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
70 #print "get_flavor_list result:", result
71 #print "get_flavor_list content:", content
73 for flavor
in flavors
:
74 flavorList
.append(flavor
['flavor_id'])
77 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
79 return result, content:
80 <0, error_text upon error
81 nb_records, flavor_list on success
84 WHERE_dict
['vnf_id'] = vnf_id
85 if nfvo_tenant
is not None:
86 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
88 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
89 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
92 imageList
.append(image
['image_id'])
95 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
96 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
97 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
98 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
99 raise exception upon error
102 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
103 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
104 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
105 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
106 if nfvo_tenant
or vim_tenant
:
107 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
108 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
109 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
112 from_
= 'datacenters as d'
113 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
115 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
118 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
119 if vim
["config"] != None:
120 extra
.update(yaml
.load(vim
["config"]))
121 if vim
["type"] not in vimconn_imported
:
124 module
= "vimconn_" + vim
["type"]
125 module_info
= imp
.find_module(module
)
126 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
127 vimconn_imported
[vim
["type"]] = vim_conn
128 except (IOError, ImportError) as e
:
129 if module_info
and module_info
[0]:
130 file.close(module_info
[0])
131 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
132 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
136 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
137 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
138 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
139 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
), tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
140 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
141 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
144 except Exception as e
:
145 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
147 except db_base_Exception
as e
:
148 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
150 def rollback(mydb
, vims
, rollback_list
):
152 #delete things by reverse order
153 for i
in range(len(rollback_list
)-1, -1, -1):
154 item
= rollback_list
[i
]
155 if item
["where"]=="vim":
156 if item
["vim_id"] not in vims
:
158 vim
=vims
[ item
["vim_id"] ]
160 if item
["what"]=="image":
161 vim
.delete_image(item
["uuid"])
162 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
163 elif item
["what"]=="flavor":
164 vim
.delete_flavor(item
["uuid"])
165 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
166 elif item
["what"]=="network":
167 vim
.delete_network(item
["uuid"])
168 elif item
["what"]=="vm":
169 vim
.delete_vminstance(item
["uuid"])
170 except vimconn
.vimconnException
as e
:
171 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
172 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
173 except db_base_Exception
as e
:
174 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
178 if item
["what"]=="image":
179 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
180 elif item
["what"]=="flavor":
181 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
182 except db_base_Exception
as e
:
183 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
184 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
185 if len(undeleted_items
)==0:
186 return True," Rollback successful."
188 return False," Rollback fails to delete: " + str(undeleted_items
)
190 def check_vnf_descriptor(vnf_descriptor
):
192 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
194 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
196 #dataplane interfaces
197 for numa
in vnfc
.get("numas",() ):
198 for interface
in numa
.get("interfaces",()):
199 if interface
["name"] in name_list
:
200 raise NfvoException("Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC"\
201 .format(vnfc
["name"], interface
["name"]),
203 name_list
.append( interface
["name"] )
205 for interface
in vnfc
.get("bridge-ifaces",() ):
206 if interface
["name"] in name_list
:
207 raise NfvoException("Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC"\
208 .format(vnfc
["name"], interface
["name"]),
210 name_list
.append( interface
["name"] )
211 vnfc_interfaces
[ vnfc
["name"] ] = name_list
213 #check if the info in external_connections matches with the one in the vnfcs
215 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
216 if external_connection
["name"] in name_list
:
217 raise NfvoException("Error at vnf:external-connections:name, value '{}' already used as an external-connection"\
218 .format(external_connection
["name"]),
220 name_list
.append(external_connection
["name"])
221 if external_connection
["VNFC"] not in vnfc_interfaces
:
222 raise NfvoException("Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC"\
223 .format(external_connection
["name"], external_connection
["VNFC"]),
226 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
227 raise NfvoException("Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC"\
228 .format(external_connection
["name"], external_connection
["local_iface_name"]),
231 #check if the info in internal_connections matches with the one in the vnfcs
233 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
234 if internal_connection
["name"] in name_list
:
235 raise NfvoException("Error at vnf:internal-connections:name, value '%s' already used as an internal-connection"\
236 .format(internal_connection
["name"]),
238 name_list
.append(internal_connection
["name"])
239 #We should check that internal-connections of type "ptp" have only 2 elements
240 if len(internal_connection
["elements"])>2 and internal_connection
["type"] == "ptp":
241 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements, size must be 2 for a type:'ptp'"\
242 .format(internal_connection
["name"]),
244 for port
in internal_connection
["elements"]:
245 if port
["VNFC"] not in vnfc_interfaces
:
246 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC"\
247 .format(internal_connection
["name"], port
["VNFC"]),
249 if port
["local_iface_name"] not in vnfc_interfaces
[ port
["VNFC"] ]:
250 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC"\
251 .format(internal_connection
["name"], port
["local_iface_name"]),
253 return -HTTP_Bad_Request
,
255 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
257 if only_create_at_vim
:
258 image_mano_id
= image_dict
['uuid']
260 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
262 image_mano_id
= images
[0]['uuid']
265 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
266 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None)
268 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
269 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
270 #create image at every vim
271 for vim_id
,vim
in vims
.iteritems():
272 image_created
="false"
274 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
275 #look at VIM if this image exist
277 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
278 except vimconn
.vimconnNotFoundException
as e
:
279 #Create the image in VIM
281 image_vim_id
= vim
.new_image(image_dict
)
282 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
284 except vimconn
.vimconnException
as e
:
286 logger
.error("Error creating image at VIM: %s", str(e
))
288 image_vim_id
= str(e
)
289 logger
.warn("Error creating image at VIM: %s", str(e
))
291 except vimconn
.vimconnException
as e
:
292 logger
.warn("Error contacting VIM to know if the image exist at VIM: %s", str(e
))
293 image_vim_id
= str(e
)
295 #if reach here the image has been create or exist
297 #add new vim_id at datacenters_images
298 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
299 elif image_db
[0]["vim_id"]!=image_vim_id
:
300 #modify existing vim_id at datacenters_images
301 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
303 return image_vim_id
if only_create_at_vim
else image_mano_id
305 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
306 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
307 'ram':flavor_dict
.get('ram'),
308 'vcpus':flavor_dict
.get('vcpus'),
310 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
311 del flavor_dict
['extended']
312 if 'extended' in flavor_dict
:
313 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
315 #look if flavor exist
316 if only_create_at_vim
:
317 flavor_mano_id
= flavor_dict
['uuid']
319 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
321 flavor_mano_id
= flavors
[0]['uuid']
324 #create one by one the images of aditional disks
325 dev_image_list
=[] #list of images
326 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
328 for device
in flavor_dict
['extended'].get('devices',[]):
329 if "image" not in device
:
331 image_dict
={'location':device
['image'], 'name':flavor_dict
['name']+str(dev_nb
)+"-img", 'description':flavor_dict
.get('description')}
332 image_metadata_dict
= device
.get('image metadata', None)
333 image_metadata_str
= None
334 if image_metadata_dict
!= None:
335 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
336 image_dict
['metadata']=image_metadata_str
337 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
338 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
339 dev_image_list
.append(image_id
)
341 temp_flavor_dict
['name'] = flavor_dict
['name']
342 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
343 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
344 flavor_mano_id
= content
345 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
346 #create flavor at every vim
347 if 'uuid' in flavor_dict
:
348 del flavor_dict
['uuid']
350 for vim_id
,vim
in vims
.items():
351 flavor_created
="false"
353 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
354 #look at VIM if this flavor exist SKIPPED
355 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
357 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
361 #Create the flavor in VIM
362 #Translate images at devices from MANO id to VIM id
363 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
364 #make a copy of original devices
366 for device
in flavor_dict
["extended"].get("devices",[]):
369 devices_original
.append(dev
)
370 if 'image' in device
:
372 if 'image metadata' in device
:
373 del device
['image metadata']
375 for index
in range(0,len(devices_original
)) :
376 device
=devices_original
[index
]
377 if "image" not in device
:
379 image_dict
={'location':device
['image'], 'name':flavor_dict
['name']+str(dev_nb
)+"-img", 'description':flavor_dict
.get('description')}
380 image_metadata_dict
= device
.get('image metadata', None)
381 image_metadata_str
= None
382 if image_metadata_dict
!= None:
383 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
384 image_dict
['metadata']=image_metadata_str
385 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
386 image_dict
["uuid"]=image_mano_id
387 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
388 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
391 #check that this vim_id exist in VIM, if not create
392 flavor_vim_id
=flavor_db
[0]["vim_id"]
394 vim
.get_flavor(flavor_vim_id
)
395 continue #flavor exist
396 except vimconn
.vimconnException
:
398 #create flavor at vim
399 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
401 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
402 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
403 flavor_created
="true"
404 except vimconn
.vimconnException
as e
:
406 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
408 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
410 #if reach here the flavor has been create or exist
411 if len(flavor_db
)==0:
412 #add new vim_id at datacenters_flavors
413 mydb
.new_row('datacenters_flavors', {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
, 'created':flavor_created
})
414 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
415 #modify existing vim_id at datacenters_flavors
416 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
418 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
420 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
423 # Step 1. Check the VNF descriptor
424 check_vnf_descriptor(vnf_descriptor
)
425 # Step 2. Check tenant exist
426 if tenant_id
!= "any":
427 check_tenant(mydb
, tenant_id
)
428 if "tenant_id" in vnf_descriptor
["vnf"]:
429 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
430 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
433 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
434 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
435 vims
= get_vim(mydb
, tenant_id
)
439 # Step 4. Review the descriptor and add missing fields
440 #print vnf_descriptor
441 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
442 vnf_name
= vnf_descriptor
['vnf']['name']
443 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
444 if "physical" in vnf_descriptor
['vnf']:
445 del vnf_descriptor
['vnf']['physical']
446 #print vnf_descriptor
447 # Step 5. Check internal connections
448 # TODO: to be moved to step 1????
449 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
450 for ic
in internal_connections
:
451 if len(ic
['elements'])>2 and ic
['type']=='ptp':
452 raise NfvoException("Mismatch 'type':'ptp' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'data'".format(len(ic
), ic
['name']),
454 elif len(ic
['elements'])==2 and ic
['type']=='data':
455 raise NfvoException("Mismatch 'type':'data' with 2 elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'ptp'".format(ic
['name']),
458 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
459 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
460 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
462 #For each VNFC, we add it to the VNFCDict and we create a flavor.
463 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
464 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
466 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
467 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
469 VNFCitem
["name"] = vnfc
['name']
470 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
472 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
475 myflavorDict
["name"] = vnfc
['name']+"-flv"
476 myflavorDict
["description"] = VNFCitem
["description"]
477 myflavorDict
["ram"] = vnfc
.get("ram", 0)
478 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
479 myflavorDict
["disk"] = vnfc
.get("disk", 1)
480 myflavorDict
["extended"] = {}
482 devices
= vnfc
.get("devices")
484 myflavorDict
["extended"]["devices"] = devices
487 # 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
488 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
490 # Previous code has been commented
491 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
492 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
493 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
494 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
496 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
498 # print "Error creating flavor: unknown processor model. Rollback successful."
499 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
501 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
502 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
504 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
505 myflavorDict
['extended']['numas'] = vnfc
['numas']
509 # Step 6.2 New flavors are created in the VIM
510 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
512 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
513 VNFCitem
["flavor_id"] = flavor_id
514 VNFCDict
[vnfc
['name']] = VNFCitem
516 logger
.debug("Creating new images in the VIM for each VNFC")
517 # Step 6.3 New images are created in the VIM
518 #For each VNFC, we must create the appropriate image.
519 #This "for" loop might be integrated with the previous one
520 #In case this integration is made, the VNFCDict might become a VNFClist.
521 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
522 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
523 image_dict
={'location':vnfc
['VNFC image'], 'name':vnfc
['name']+"-img", 'description':VNFCDict
[vnfc
['name']]['description']}
524 image_metadata_dict
= vnfc
.get('image metadata', None)
525 image_metadata_str
= None
526 if image_metadata_dict
is not None:
527 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
528 image_dict
['metadata']=image_metadata_str
529 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
530 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
531 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
532 VNFCDict
[vnfc
['name']]["image_id"] = image_id
533 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
['VNFC image']
536 # Step 7. Storing the VNF descriptor in the repository
537 if "descriptor" not in vnf_descriptor
["vnf"]:
538 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
540 # Step 8. Adding the VNF to the NFVO DB
541 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
543 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
544 _
, message
= rollback(mydb
, vims
, rollback_list
)
545 if isinstance(e
, db_base_Exception
):
546 error_text
= "Exception at database"
547 elif isinstance(e
, KeyError):
548 error_text
= "KeyError exception "
549 e
.http_code
= HTTP_Internal_Server_Error
551 error_text
= "Exception at VIM"
552 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
553 #logger.error("start_scenario %s", error_text)
554 raise NfvoException(error_text
, e
.http_code
)
556 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
559 # Step 1. Check the VNF descriptor
560 check_vnf_descriptor(vnf_descriptor
)
561 # Step 2. Check tenant exist
562 if tenant_id
!= "any":
563 check_tenant(mydb
, tenant_id
)
564 if "tenant_id" in vnf_descriptor
["vnf"]:
565 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
566 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
569 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
570 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
571 vims
= get_vim(mydb
, tenant_id
)
575 # Step 4. Review the descriptor and add missing fields
576 #print vnf_descriptor
577 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
578 vnf_name
= vnf_descriptor
['vnf']['name']
579 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
580 if "physical" in vnf_descriptor
['vnf']:
581 del vnf_descriptor
['vnf']['physical']
582 #print vnf_descriptor
583 # Step 5. Check internal connections
584 # TODO: to be moved to step 1????
585 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
586 for ic
in internal_connections
:
587 if len(ic
['elements'])>2 and ic
['type']=='e-line':
588 raise NfvoException("Mismatch 'type':'e-line' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'e-lan'".format(len(ic
), ic
['name']),
591 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
592 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
593 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
595 #For each VNFC, we add it to the VNFCDict and we create a flavor.
596 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
597 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
599 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
600 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
602 VNFCitem
["name"] = vnfc
['name']
603 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
605 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
608 myflavorDict
["name"] = vnfc
['name']+"-flv"
609 myflavorDict
["description"] = VNFCitem
["description"]
610 myflavorDict
["ram"] = vnfc
.get("ram", 0)
611 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
612 myflavorDict
["disk"] = vnfc
.get("disk", 1)
613 myflavorDict
["extended"] = {}
615 devices
= vnfc
.get("devices")
617 myflavorDict
["extended"]["devices"] = devices
620 # 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
621 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
623 # Previous code has been commented
624 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
625 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
626 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
627 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
629 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
631 # print "Error creating flavor: unknown processor model. Rollback successful."
632 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
634 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
635 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
637 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
638 myflavorDict
['extended']['numas'] = vnfc
['numas']
642 # Step 6.2 New flavors are created in the VIM
643 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
645 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
646 VNFCitem
["flavor_id"] = flavor_id
647 VNFCDict
[vnfc
['name']] = VNFCitem
649 logger
.debug("Creating new images in the VIM for each VNFC")
650 # Step 6.3 New images are created in the VIM
651 #For each VNFC, we must create the appropriate image.
652 #This "for" loop might be integrated with the previous one
653 #In case this integration is made, the VNFCDict might become a VNFClist.
654 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
655 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
656 image_dict
={'location':vnfc
['VNFC image'], 'name':vnfc
['name']+"-img", 'description':VNFCDict
[vnfc
['name']]['description']}
657 image_metadata_dict
= vnfc
.get('image metadata', None)
658 image_metadata_str
= None
659 if image_metadata_dict
is not None:
660 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
661 image_dict
['metadata']=image_metadata_str
662 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
663 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
664 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
665 VNFCDict
[vnfc
['name']]["image_id"] = image_id
666 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
['VNFC image']
669 # Step 7. Storing the VNF descriptor in the repository
670 if "descriptor" not in vnf_descriptor
["vnf"]:
671 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
673 # Step 8. Adding the VNF to the NFVO DB
674 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
676 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
677 _
, message
= rollback(mydb
, vims
, rollback_list
)
678 if isinstance(e
, db_base_Exception
):
679 error_text
= "Exception at database"
680 elif isinstance(e
, KeyError):
681 error_text
= "KeyError exception "
682 e
.http_code
= HTTP_Internal_Server_Error
684 error_text
= "Exception at VIM"
685 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
686 #logger.error("start_scenario %s", error_text)
687 raise NfvoException(error_text
, e
.http_code
)
689 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
690 #check valid tenant_id
691 check_tenant(mydb
, tenant_id
)
694 if tenant_id
!= "any":
695 where_or
["tenant_id"] = tenant_id
696 where_or
["public"] = True
697 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
700 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
701 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
702 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
703 data
={'vnf' : filtered_content
}
705 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
706 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description'),
707 WHERE
={'vnfs.uuid': vnf_id
} )
709 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
711 data
['vnf']['VNFC'] = content
712 #TODO: GET all the information from a VNFC and include it in the output.
715 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
716 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
717 WHERE
={'vnfs.uuid': vnf_id
} )
718 data
['vnf']['nets'] = content
720 #GET ip-profile for each net
721 for net
in data
['vnf']['nets']:
722 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
723 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
724 WHERE
={'net_id': net
["uuid"]} )
725 if len(ipprofiles
)==1:
726 net
["ip_profile"] = ipprofiles
[0]
727 elif len(ipprofiles
)>1:
728 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
731 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
733 #GET External Interfaces
734 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
735 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
736 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
737 WHERE
={'vnfs.uuid': vnf_id
},
738 WHERE_NOT
={'interfaces.external_name': None} )
740 data
['vnf']['external-connections'] = content
745 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
747 if tenant_id
!= "any":
748 check_tenant(mydb
, tenant_id
)
749 # Get the URL of the VIM from the nfvo_tenant and the datacenter
750 vims
= get_vim(mydb
, tenant_id
)
754 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
756 if tenant_id
!= "any":
757 where_or
["tenant_id"] = tenant_id
758 where_or
["public"] = True
759 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
762 # "Getting the list of flavors and tenants of the VNF"
763 flavorList
= get_flavorlist(mydb
, vnf_id
)
764 if len(flavorList
)==0:
765 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
767 imageList
= get_imagelist(mydb
, vnf_id
)
768 if len(imageList
)==0:
769 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
771 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
773 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
776 for flavor
in flavorList
:
777 #check if flavor is used by other vnf
779 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
781 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
783 #flavor not used, must be deleted
785 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
787 if flavor_vim
["datacenter_id"] not in vims
:
789 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
791 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
793 myvim
.delete_flavor(flavor_vim
["vim_id"])
794 except vimconn
.vimconnNotFoundException
as e
:
795 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
796 except vimconn
.vimconnException
as e
:
797 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
798 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
799 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
800 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
801 mydb
.delete_row_by_id('flavors', flavor
)
802 except db_base_Exception
as e
:
803 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
804 undeletedItems
.append("flavor %s" % flavor
)
807 for image
in imageList
:
809 #check if image is used by other vnf
810 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
812 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
814 #image not used, must be deleted
816 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
818 if image_vim
["datacenter_id"] not in vims
:
820 if image_vim
['created']=='false': #skip this image because not created by openmano
822 myvim
=vims
[ image_vim
["datacenter_id"] ]
824 myvim
.delete_image(image_vim
["vim_id"])
825 except vimconn
.vimconnNotFoundException
as e
:
826 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
827 except vimconn
.vimconnException
as e
:
828 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
829 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
830 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
831 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
832 mydb
.delete_row_by_id('images', image
)
833 except db_base_Exception
as e
:
834 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
835 undeletedItems
.append("image %s" % image
)
837 return vnf_id
+ " " + vnf
["name"]
839 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
841 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
842 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
846 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
847 myvim
= vims
.values()[0]
848 result
,servers
= myvim
.get_hosts_info()
850 return result
, servers
851 topology
= {'name':myvim
['name'] , 'servers': servers
}
852 return result
, topology
854 def get_hosts(mydb
, nfvo_tenant_id
):
855 vims
= get_vim(mydb
, nfvo_tenant_id
)
857 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
859 #print "nfvo.datacenter_action() error. Several datacenters found"
860 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
861 myvim
= vims
.values()[0]
863 hosts
= myvim
.get_hosts()
864 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
866 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
868 server
={'name':host
['name'], 'vms':[]}
869 for vm
in host
['instances']:
870 #get internal name and model
872 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
873 WHERE
={'vim_vm_id':vm
['id']} )
875 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
877 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
879 except db_base_Exception
as e
:
880 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
881 datacenter
['Datacenters'][0]['servers'].append(server
)
882 #return -400, "en construccion"
884 #print 'datacenters '+ json.dumps(datacenter, indent=4)
886 except vimconn
.vimconnException
as e
:
887 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
889 def new_scenario(mydb
, tenant_id
, topo
):
891 # result, vims = get_vim(mydb, tenant_id)
893 # return result, vims
895 if tenant_id
!= "any":
896 check_tenant(mydb
, tenant_id
)
897 if "tenant_id" in topo
:
898 if topo
["tenant_id"] != tenant_id
:
899 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
904 #1.1: get VNFs and external_networks (other_nets).
906 other_nets
={} #external_networks, bridge_networks and data_networkds
907 nodes
= topo
['topology']['nodes']
908 for k
in nodes
.keys():
909 if nodes
[k
]['type'] == 'VNF':
911 vnfs
[k
]['ifaces'] = {}
912 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
913 other_nets
[k
] = nodes
[k
]
914 other_nets
[k
]['external']=True
915 elif nodes
[k
]['type'] == 'network':
916 other_nets
[k
] = nodes
[k
]
917 other_nets
[k
]['external']=False
920 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
921 for name
,vnf
in vnfs
.items():
923 where_or
={"tenant_id": tenant_id
, 'public': "true"}
925 error_pos
= "'topology':'nodes':'" + name
+ "'"
927 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
928 where
['uuid'] = vnf
['vnf_id']
929 if 'VNF model' in vnf
:
930 error_text
+= " 'VNF model' " + vnf
['VNF model']
931 where
['name'] = vnf
['VNF model']
933 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
935 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
941 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
943 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
944 vnf
['uuid']=vnf_db
[0]['uuid']
945 vnf
['description']=vnf_db
[0]['description']
946 #get external interfaces
947 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
948 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
949 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
950 for ext_iface
in ext_ifaces
:
951 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
953 #1.4 get list of connections
954 conections
= topo
['topology']['connections']
956 for k
in conections
.keys():
957 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
958 ifaces_list
= conections
[k
]['nodes'].items()
959 elif type(conections
[k
]['nodes'])==list: #list with dictionary
961 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
962 for k2
in conection_pair_list
:
965 con_type
= conections
[k
].get("type", "link")
966 if con_type
!= "link":
968 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
969 other_nets
[k
] = {'external': False}
970 if conections
[k
].get("graph"):
971 other_nets
[k
]["graph"] = conections
[k
]["graph"]
972 ifaces_list
.append( (k
, None) )
975 if con_type
== "external_network":
976 other_nets
[k
]['external'] = True
977 if conections
[k
].get("model"):
978 other_nets
[k
]["model"] = conections
[k
]["model"]
980 other_nets
[k
]["model"] = k
981 if con_type
== "dataplane_net" or con_type
== "bridge_net":
982 other_nets
[k
]["model"] = con_type
985 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)
986 #print set(ifaces_list)
987 #check valid VNF and iface names
988 for iface
in ifaces_list
:
989 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
990 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
991 str(k
), iface
[0]), HTTP_Not_Found
)
992 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
993 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
994 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
996 #1.5 unify connections from the pair list to a consolidated list
998 while index
< len(conections_list
):
1000 while index2
< len(conections_list
):
1001 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1002 conections_list
[index
] |
= conections_list
[index2
]
1003 del conections_list
[index2
]
1006 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1008 #for k in conections_list:
1013 #1.6 Delete non external nets
1014 # for k in other_nets.keys():
1015 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1016 # for con in conections_list:
1018 # for index in range(0,len(con)):
1019 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1020 # for index in delete_indexes:
1023 #1.7: Check external_ports are present at database table datacenter_nets
1024 for k
,net
in other_nets
.items():
1025 error_pos
= "'topology':'nodes':'" + k
+ "'"
1026 if net
['external']==False:
1027 if 'name' not in net
:
1029 if 'model' not in net
:
1030 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1031 if net
['model']=='bridge_net':
1032 net
['type']='bridge';
1033 elif net
['model']=='dataplane_net':
1036 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1038 #IF we do not want to check that external network exist at datacenter
1043 # if 'net_id' in net:
1044 # error_text += " 'net_id' " + net['net_id']
1045 # WHERE_['uuid'] = net['net_id']
1046 # if 'model' in net:
1047 # error_text += " 'model' " + net['model']
1048 # WHERE_['name'] = net['model']
1049 # if len(WHERE_) == 0:
1050 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1051 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1052 # FROM='datacenter_nets', WHERE=WHERE_ )
1054 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1056 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1057 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1059 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1060 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1061 # other_nets[k].update(net_db[0])
1064 net_nb
=0 #Number of nets
1065 for con
in conections_list
:
1066 #check if this is connected to a external net
1070 for index
in range(0,len(con
)):
1071 #check if this is connected to a external net
1072 for net_key
in other_nets
.keys():
1073 if con
[index
][0]==net_key
:
1074 if other_net_index
>=0:
1075 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1076 #print "nfvo.new_scenario " + error_text
1077 raise NfvoException(error_text
, HTTP_Bad_Request
)
1079 other_net_index
= index
1080 net_target
= net_key
1082 #print "other_net_index", other_net_index
1084 if other_net_index
>=0:
1085 del con
[other_net_index
]
1086 #IF we do not want to check that external network exist at datacenter
1087 if other_nets
[net_target
]['external'] :
1088 if "name" not in other_nets
[net_target
]:
1089 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1090 if other_nets
[net_target
]["type"] == "external_network":
1091 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1092 other_nets
[net_target
]["type"] = "data"
1094 other_nets
[net_target
]["type"] = "bridge"
1096 # if other_nets[net_target]['external'] :
1097 # 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
1098 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1099 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1100 # print "nfvo.new_scenario " + error_text
1101 # return -HTTP_Bad_Request, error_text
1104 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1107 net_type_bridge
=False
1109 net_target
= "__-__net"+str(net_nb
)
1110 net_list
[net_target
] = {'name': "net-"+str(net_nb
), 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1113 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1114 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1115 if iface_type
=='mgmt' or iface_type
=='bridge':
1116 net_type_bridge
= True
1118 net_type_data
= True
1119 if net_type_bridge
and net_type_data
:
1120 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1121 #print "nfvo.new_scenario " + error_text
1122 raise NfvoException(error_text
, HTTP_Bad_Request
)
1123 elif net_type_bridge
:
1126 type_
='data' if len(con
)>2 else 'ptp'
1127 net_list
[net_target
]['type'] = type_
1130 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1131 #print "nfvo.new_scenario " + error_text
1133 raise NfvoException(error_text
, HTTP_Bad_Request
)
1135 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1136 #1.8.1 obtain management net
1137 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1138 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1139 #1.8.2 check all interfaces from all vnfs
1141 add_mgmt_net
= False
1142 for vnf
in vnfs
.values():
1143 for iface
in vnf
['ifaces'].values():
1144 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1145 #iface not connected
1146 iface
['net_key'] = 'mgmt'
1148 if add_mgmt_net
and 'mgmt' not in net_list
:
1149 net_list
['mgmt']=mgmt_net
[0]
1150 net_list
['mgmt']['external']=True
1151 net_list
['mgmt']['graph']={'visible':False}
1153 net_list
.update(other_nets
)
1155 #print 'net_list', net_list
1160 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1161 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1162 'tenant_id':tenant_id
, 'name':topo
['name'],
1163 'description':topo
.get('description',topo
['name']),
1164 'public': topo
.get('public', False)
1169 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
):
1170 scenario
= scenario_dict
["scenario"]
1171 if tenant_id
!= "any":
1172 check_tenant(mydb
, tenant_id
)
1173 if "tenant_id" in scenario
:
1174 if scenario
["tenant_id"] != tenant_id
:
1175 print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1176 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1177 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1181 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1182 for name
,vnf
in scenario
["vnfs"].iteritems():
1184 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1186 error_pos
= "'topology':'nodes':'" + name
+ "'"
1188 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1189 where
['uuid'] = vnf
['vnf_id']
1190 if 'vnf_name' in vnf
:
1191 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1192 where
['name'] = vnf
['vnf_name']
1194 raise NfvoException("Needed a 'vnf_id' or 'VNF model' at " + error_pos
, HTTP_Bad_Request
)
1195 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1201 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1203 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1204 vnf
['uuid']=vnf_db
[0]['uuid']
1205 vnf
['description']=vnf_db
[0]['description']
1207 #get external interfaces
1208 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1209 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1210 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1211 for ext_iface
in ext_ifaces
:
1212 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1214 #2: Insert net_key at every vnf interface
1215 for net_name
,net
in scenario
["networks"].iteritems():
1216 net_type_bridge
=False
1218 for iface_dict
in net
["interfaces"]:
1219 for vnf
,iface
in iface_dict
.iteritems():
1220 if vnf
not in scenario
["vnfs"]:
1221 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1222 #print "nfvo.new_scenario_v02 " + error_text
1223 raise NfvoException(error_text
, HTTP_Not_Found
)
1224 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1225 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1226 #print "nfvo.new_scenario_v02 " + error_text
1227 raise NfvoException(error_text
, HTTP_Bad_Request
)
1228 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1229 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1230 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1231 #print "nfvo.new_scenario_v02 " + error_text
1232 raise NfvoException(error_text
, HTTP_Bad_Request
)
1233 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1234 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1235 if iface_type
=='mgmt' or iface_type
=='bridge':
1236 net_type_bridge
= True
1238 net_type_data
= True
1239 if net_type_bridge
and net_type_data
:
1240 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1241 #print "nfvo.new_scenario " + error_text
1242 raise NfvoException(error_text
, HTTP_Bad_Request
)
1243 elif net_type_bridge
:
1246 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1248 net
['name'] = net_name
1249 net
['external'] = net
.get('external', False)
1251 #3: insert at database
1252 scenario
["nets"] = scenario
["networks"]
1253 scenario
['tenant_id'] = tenant_id
1254 scenario_id
= mydb
.new_scenario( scenario
)
1257 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1258 data
["uuid"] = scenario_id
1259 data
["tenant_id"] = tenant_id
1260 c
= mydb
.edit_scenario( data
)
1263 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1264 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1265 datacenter_id
= None
1266 datacenter_name
=None
1267 if datacenter
!= None:
1268 if utils
.check_valid_uuid(datacenter
):
1269 datacenter_id
= datacenter
1271 datacenter_name
= datacenter
1272 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
)
1274 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
1276 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
1277 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1278 myvim
= vims
.values()[0]
1279 myvim_tenant
= myvim
['tenant_id']
1280 datacenter_id
= myvim
['id']
1281 datacenter_name
= myvim
['name']
1282 datacenter_tenant_id
= myvim
['config']['datacenter_tenant_id']
1285 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1286 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1287 scenarioDict
['datacenter_tenant_id'] = datacenter_tenant_id
1288 scenarioDict
['datacenter_id'] = datacenter_id
1289 #print '================scenarioDict======================='
1290 #print json.dumps(scenarioDict, indent=4)
1291 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1293 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1294 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1296 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1297 auxNetDict
['scenario'] = {}
1299 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1300 for sce_net
in scenarioDict
['nets']:
1301 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1303 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1304 myNetName
= myNetName
[0:255] #limit length
1305 myNetType
= sce_net
['type']
1307 myNetDict
["name"] = myNetName
1308 myNetDict
["type"] = myNetType
1309 myNetDict
["tenant_id"] = myvim_tenant
1310 myNetIPProfile
= sce_net
.get('ip_profile', None)
1312 #We should use the dictionary as input parameter for new_network
1314 if not sce_net
["external"]:
1315 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1316 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1317 sce_net
['vim_id'] = network_id
1318 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1319 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1321 if sce_net
['vim_id'] == None:
1322 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1323 _
, message
= rollback(mydb
, vims
, rollbackList
)
1324 logger
.error("nfvo.start_scenario: %s", error_text
)
1325 raise NfvoException(error_text
, HTTP_Bad_Request
)
1326 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1327 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1329 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1330 #For each vnf net, we create it and we add it to instanceNetlist.
1331 for sce_vnf
in scenarioDict
['vnfs']:
1332 for net
in sce_vnf
['nets']:
1333 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1335 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1336 myNetName
= myNetName
[0:255] #limit length
1337 myNetType
= net
['type']
1339 myNetDict
["name"] = myNetName
1340 myNetDict
["type"] = myNetType
1341 myNetDict
["tenant_id"] = myvim_tenant
1342 myNetIPProfile
= net
.get('ip_profile', None)
1345 #We should use the dictionary as input parameter for new_network
1346 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1347 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1348 net
['vim_id'] = network_id
1349 if sce_vnf
['uuid'] not in auxNetDict
:
1350 auxNetDict
[sce_vnf
['uuid']] = {}
1351 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1352 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1354 #print "auxNetDict:"
1355 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1357 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1358 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1360 for sce_vnf
in scenarioDict
['vnfs']:
1361 for vm
in sce_vnf
['vms']:
1364 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1365 myVMDict
['name'] = "%s.%s.%d" % (instance_scenario_name
,sce_vnf
['name'],i
)
1366 #myVMDict['description'] = vm['description']
1367 myVMDict
['description'] = myVMDict
['name'][0:99]
1369 myVMDict
['start'] = "no"
1370 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1371 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1373 #create image at vim in case it not exist
1374 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1375 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1376 vm
['vim_image_id'] = image_id
1378 #create flavor at vim in case it not exist
1379 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1380 if flavor_dict
['extended']!=None:
1381 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1382 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1383 vm
['vim_flavor_id'] = flavor_id
1386 myVMDict
['imageRef'] = vm
['vim_image_id']
1387 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1388 myVMDict
['networks'] = []
1389 for iface
in vm
['interfaces']:
1391 if iface
['type']=="data":
1392 netDict
['type'] = iface
['model']
1393 elif "model" in iface
and iface
["model"]!=None:
1394 netDict
['model']=iface
['model']
1395 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1396 #discover type of interface looking at flavor
1397 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1398 for flavor_iface
in numa
.get('interfaces',[]):
1399 if flavor_iface
.get('name') == iface
['internal_name']:
1400 if flavor_iface
['dedicated'] == 'yes':
1401 netDict
['type']="PF" #passthrough
1402 elif flavor_iface
['dedicated'] == 'no':
1403 netDict
['type']="VF" #siov
1404 elif flavor_iface
['dedicated'] == 'yes:sriov':
1405 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1406 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1408 netDict
["use"]=iface
['type']
1409 if netDict
["use"]=="data" and not netDict
.get("type"):
1410 #print "netDict", netDict
1411 #print "iface", iface
1412 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'])
1413 if flavor_dict
.get('extended')==None:
1414 raise NfvoException(e_text
+ "After database migration some information is not available. \
1415 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1417 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1418 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1419 netDict
["type"]="virtual"
1420 if "vpci" in iface
and iface
["vpci"] is not None:
1421 netDict
['vpci'] = iface
['vpci']
1422 if "mac" in iface
and iface
["mac"] is not None:
1423 netDict
['mac_address'] = iface
['mac']
1424 netDict
['name'] = iface
['internal_name']
1425 if iface
['net_id'] is None:
1426 for vnf_iface
in sce_vnf
["interfaces"]:
1429 if vnf_iface
['interface_id']==iface
['uuid']:
1430 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1433 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1434 #skip bridge ifaces not connected to any net
1435 #if 'net_id' not in netDict or netDict['net_id']==None:
1437 myVMDict
['networks'].append(netDict
)
1438 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1439 #print myVMDict['name']
1440 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1441 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1442 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1443 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1444 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1445 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1446 vm
['vim_id'] = vm_id
1447 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1448 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1449 for net
in myVMDict
['networks']:
1451 for iface
in vm
['interfaces']:
1452 if net
["name"]==iface
["internal_name"]:
1453 iface
["vim_id"]=net
["vim_id"]
1456 logger
.debug("start scenario Deployment done")
1457 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1458 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1459 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1460 return mydb
.get_instance_scenario(instance_id
)
1462 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1463 _
, message
= rollback(mydb
, vims
, rollbackList
)
1464 if isinstance(e
, db_base_Exception
):
1465 error_text
= "Exception at database"
1467 error_text
= "Exception at VIM"
1468 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1469 #logger.error("start_scenario %s", error_text)
1470 raise NfvoException(error_text
, e
.http_code
)
1472 def unify_cloud_config(cloud_config
):
1473 index_to_delete
= []
1474 users
= cloud_config
.get("users", [])
1475 for index0
in range(0,len(users
)):
1476 if index0
in index_to_delete
:
1478 for index1
in range(index0
+1,len(users
)):
1479 if index1
in index_to_delete
:
1481 if users
[index0
]["name"] == users
[index1
]["name"]:
1482 index_to_delete
.append(index1
)
1483 for key
in users
[index1
].get("key-pairs",()):
1484 if "key-pairs" not in users
[index0
]:
1485 users
[index0
]["key-pairs"] = [key
]
1486 elif key
not in users
[index0
]["key-pairs"]:
1487 users
[index0
]["key-pairs"].append(key
)
1488 index_to_delete
.sort(reverse
=True)
1489 for index
in index_to_delete
:
1492 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None):
1493 datacenter_id
= None
1494 datacenter_name
= None
1495 if datacenter_id_name
:
1496 if utils
.check_valid_uuid(datacenter_id_name
):
1497 datacenter_id
= datacenter_id_name
1499 datacenter_name
= datacenter_id_name
1500 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
=None)
1502 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1504 #print "nfvo.datacenter_action() error. Several datacenters found"
1505 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1506 return vims
.keys()[0], vims
.values()[0]
1508 def new_scenario_v03(mydb
, tenant_id
, scenario_dict
):
1509 scenario
= scenario_dict
["scenario"]
1510 if tenant_id
!= "any":
1511 check_tenant(mydb
, tenant_id
)
1512 if "tenant_id" in scenario
:
1513 if scenario
["tenant_id"] != tenant_id
:
1514 logger("Tenant '%s' not found", tenant_id
)
1515 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1516 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1520 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1521 for name
,vnf
in scenario
["vnfs"].iteritems():
1523 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1525 error_pos
= "'topology':'nodes':'" + name
+ "'"
1527 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1528 where
['uuid'] = vnf
['vnf_id']
1529 if 'vnf_name' in vnf
:
1530 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1531 where
['name'] = vnf
['vnf_name']
1533 raise NfvoException("Needed a 'vnf_id' or 'VNF model' at " + error_pos
, HTTP_Bad_Request
)
1534 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1540 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1542 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1543 vnf
['uuid']=vnf_db
[0]['uuid']
1544 vnf
['description']=vnf_db
[0]['description']
1546 # get external interfaces
1547 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1548 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1549 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1550 for ext_iface
in ext_ifaces
:
1551 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1553 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1555 #2: Insert net_key and ip_address at every vnf interface
1556 for net_name
,net
in scenario
["networks"].iteritems():
1557 net_type_bridge
=False
1559 for iface_dict
in net
["interfaces"]:
1560 logger
.debug("Iface_dict %s", iface_dict
)
1561 vnf
= iface_dict
["vnf"]
1562 iface
= iface_dict
["vnf_interface"]
1563 if vnf
not in scenario
["vnfs"]:
1564 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1565 #logger.debug(error_text)
1566 raise NfvoException(error_text
, HTTP_Not_Found
)
1567 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1568 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1569 #logger.debug(error_text)
1570 raise NfvoException(error_text
, HTTP_Bad_Request
)
1571 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1572 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1573 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1574 #logger.debug(error_text)
1575 raise NfvoException(error_text
, HTTP_Bad_Request
)
1576 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1577 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['ip_address'] = iface_dict
.get('ip_address',None)
1578 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1579 if iface_type
=='mgmt' or iface_type
=='bridge':
1580 net_type_bridge
= True
1582 net_type_data
= True
1583 if net_type_bridge
and net_type_data
:
1584 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1585 #logger.debug(error_text)
1586 raise NfvoException(error_text
, HTTP_Bad_Request
)
1587 elif net_type_bridge
:
1590 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1592 if ("implementation" in net
):
1593 if (type_
== "bridge" and net
["implementation"] == "underlay"):
1594 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at 'network':'%s'" % (net_name
)
1595 #logger.debug(error_text)
1596 raise NfvoException(error_text
, HTTP_Bad_Request
)
1597 elif (type_
<> "bridge" and net
["implementation"] == "overlay"):
1598 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at 'network':'%s'" % (net_name
)
1599 #logger.debug(error_text)
1600 raise NfvoException(error_text
, HTTP_Bad_Request
)
1601 net
.pop("implementation")
1603 if (type_
== "data" and net
["type"] == "e-line"):
1604 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type 'e-line' at 'network':'%s'" % (net_name
)
1605 #logger.debug(error_text)
1606 raise NfvoException(error_text
, HTTP_Bad_Request
)
1607 elif (type_
== "ptp" and net
["type"] == "e-lan"):
1611 net
['name'] = net_name
1612 net
['external'] = net
.get('external', False)
1614 #3: insert at database
1615 scenario
["nets"] = scenario
["networks"]
1616 scenario
['tenant_id'] = tenant_id
1617 scenario_id
= mydb
.new_scenario2(scenario
)
1621 '''Takes dict d and updates it with the values in dict u.'''
1622 '''It merges all depth levels'''
1623 for k
, v
in u
.iteritems():
1624 if isinstance(v
, collections
.Mapping
):
1625 r
= update(d
.get(k
, {}), v
)
1631 def create_instance(mydb
, tenant_id
, instance_dict
):
1632 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1633 #logger.debug("Creating instance...")
1634 scenario
= instance_dict
["scenario"]
1636 #find main datacenter
1638 datacenter
= instance_dict
.get("datacenter")
1639 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1640 myvims
[default_datacenter_id
] = vim
1641 #myvim_tenant = myvim['tenant_id']
1642 # default_datacenter_name = vim['name']
1643 default_datacenter_tenant_id
= vim
['config']['datacenter_tenant_id'] #TODO review
1646 #print "Checking that the scenario exists and getting the scenario dictionary"
1647 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1649 #logger.debug("Dictionaries before merging")
1650 #logger.debug("InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1651 #logger.debug("ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1653 scenarioDict
['datacenter_tenant_id'] = default_datacenter_tenant_id
1654 scenarioDict
['datacenter_id'] = default_datacenter_id
1656 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1657 auxNetDict
['scenario'] = {}
1659 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1660 instance_name
= instance_dict
["name"]
1661 instance_description
= instance_dict
.get("description")
1663 #0 check correct parameters
1664 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1666 for scenario_net
in scenarioDict
['nets']:
1667 if net_name
== scenario_net
["name"]:
1671 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1672 if "sites" not in net_instance_desc
:
1673 net_instance_desc
["sites"] = [ {} ]
1674 site_without_datacenter_field
= False
1675 for site
in net_instance_desc
["sites"]:
1676 if site
.get("datacenter"):
1677 if site
["datacenter"] not in myvims
:
1678 #Add this datacenter to myvims
1679 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1681 site
["datacenter"] = d
#change name to id
1683 if site_without_datacenter_field
:
1684 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1685 site_without_datacenter_field
= True
1686 site
["datacenter"] = default_datacenter_id
#change name to id
1688 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
1690 for scenario_vnf
in scenarioDict
['vnfs']:
1691 if vnf_name
== scenario_vnf
['name']:
1695 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
1696 if "datacenter" in vnf_instance_desc
:
1697 #Add this datacenter to myvims
1698 if vnf_instance_desc
["datacenter"] not in myvims
:
1699 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
1701 scenario_vnf
["datacenter"] = d
#change name to id
1702 #0.1 parse cloud-config parameters
1703 cloud_config
= scenarioDict
.get("cloud-config", {})
1704 if instance_dict
.get("cloud-config"):
1705 cloud_config
.update( instance_dict
["cloud-config"])
1706 if not cloud_config
:
1709 scenarioDict
["cloud-config"] = cloud_config
1710 unify_cloud_config(cloud_config
)
1712 #0.2 merge instance information into scenario
1713 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
1714 #However, this is not possible yet.
1715 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1716 for scenario_net
in scenarioDict
['nets']:
1717 if net_name
== scenario_net
["name"]:
1718 if 'ip-profile' in net_instance_desc
:
1719 ipprofile
= net_instance_desc
['ip-profile']
1720 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
1721 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
1722 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
1723 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
1724 if 'dhcp' in ipprofile
:
1725 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
1726 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
1727 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
1728 del ipprofile
['dhcp']
1729 update(scenario_net
['ip_profile'],ipprofile
)
1730 for interface
in net_instance_desc
['interfaces']:
1731 if 'ip_address' in interface
:
1732 for vnf
in scenarioDict
['vnfs']:
1733 if interface
['vnf'] == vnf
['name']:
1734 for vnf_interface
in vnf
['interfaces']:
1735 if interface
['vnf_interface'] == vnf_interface
['external_name']:
1736 vnf_interface
['ip_address']=interface
['ip_address']
1738 #logger.debug("Merged dictionary")
1739 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
1742 #1. Creating new nets (sce_nets) in the VIM"
1743 for sce_net
in scenarioDict
['nets']:
1744 sce_net
["vim_id_sites"]={}
1745 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
1746 net_name
= descriptor_net
.get("vim-network-name")
1747 auxNetDict
['scenario'][sce_net
['uuid']] = {}
1749 sites
= descriptor_net
.get("sites", [ {} ])
1751 if site
.get("datacenter"):
1752 vim
= myvims
[ site
["datacenter"] ]
1753 datacenter_id
= site
["datacenter"]
1755 vim
= myvims
[ default_datacenter_id
]
1756 datacenter_id
= default_datacenter_id
1758 net_type
= sce_net
['type']
1759 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
1760 if sce_net
["external"]:
1762 net_name
= sce_net
["name"]
1763 if "netmap-use" in site
or "netmap-create" in site
:
1764 create_network
= False
1765 lookfor_network
= False
1766 if "netmap-use" in site
:
1767 lookfor_network
= True
1768 if utils
.check_valid_uuid(site
["netmap-use"]):
1769 filter_text
= "scenario id '%s'" % site
["netmap-use"]
1770 lookfor_filter
["id"] = site
["netmap-use"]
1772 filter_text
= "scenario name '%s'" % site
["netmap-use"]
1773 lookfor_filter
["name"] = site
["netmap-use"]
1774 if "netmap-create" in site
:
1775 create_network
= True
1776 net_vim_name
= net_name
1777 if site
["netmap-create"]:
1778 net_vim_name
= site
["netmap-create"]
1780 elif sce_net
['vim_id'] != None:
1781 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
1782 create_network
= False
1783 lookfor_network
= True
1784 lookfor_filter
["id"] = sce_net
['vim_id']
1785 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
1786 #look for network at datacenter and return error
1788 #There is not a netmap, look at datacenter for a net with this name and create if not found
1789 create_network
= True
1790 lookfor_network
= True
1791 lookfor_filter
["name"] = sce_net
["name"]
1792 net_vim_name
= sce_net
["name"]
1793 filter_text
= "scenario name '%s'" % sce_net
["name"]
1796 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
1797 net_name
= net_name
[:255] #limit length
1798 net_vim_name
= net_name
1799 create_network
= True
1800 lookfor_network
= False
1803 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
1804 if len(vim_nets
) > 1:
1805 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1806 elif len(vim_nets
) == 0:
1807 if not create_network
:
1808 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1810 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
1812 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
1813 create_network
= False
1815 #if network is not external
1816 network_id
= vim
.new_network(net_vim_name
, net_type
, sce_net
.get('ip_profile',None))
1817 sce_net
["vim_id_sites"][datacenter_id
] = network_id
1818 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = network_id
1819 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':network_id
})
1821 #2. Creating new nets (vnf internal nets) in the VIM"
1822 #For each vnf net, we create it and we add it to instanceNetlist.
1823 for sce_vnf
in scenarioDict
['vnfs']:
1824 for net
in sce_vnf
['nets']:
1825 if sce_vnf
.get("datacenter"):
1826 vim
= myvims
[ sce_vnf
["datacenter"] ]
1827 datacenter_id
= sce_vnf
["datacenter"]
1829 vim
= myvims
[ default_datacenter_id
]
1830 datacenter_id
= default_datacenter_id
1831 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
1832 net_name
= descriptor_net
.get("name")
1834 net_name
= "%s.%s" %(instance_name
, net
["name"])
1835 net_name
= net_name
[:255] #limit length
1836 net_type
= net
['type']
1837 network_id
= vim
.new_network(net_name
, net_type
, net
.get('ip_profile',None))
1838 net
['vim_id'] = network_id
1839 if sce_vnf
['uuid'] not in auxNetDict
:
1840 auxNetDict
[sce_vnf
['uuid']] = {}
1841 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1842 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1844 #print "auxNetDict:"
1845 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1847 #3. Creating new vm instances in the VIM
1848 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1849 for sce_vnf
in scenarioDict
['vnfs']:
1850 if sce_vnf
.get("datacenter"):
1851 vim
= myvims
[ sce_vnf
["datacenter"] ]
1852 datacenter_id
= sce_vnf
["datacenter"]
1854 vim
= myvims
[ default_datacenter_id
]
1855 datacenter_id
= default_datacenter_id
1856 sce_vnf
["datacenter_id"] = datacenter_id
1857 sce_vnf
["datacenter_tenant_id"] = vim
['config']['datacenter_tenant_id']
1859 for vm
in sce_vnf
['vms']:
1862 myVMDict
['name'] = "%s.%s.%d" % (instance_name
,sce_vnf
['name'],i
)
1863 myVMDict
['description'] = myVMDict
['name'][0:99]
1865 # myVMDict['start'] = "no"
1866 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1867 #create image at vim in case it not exist
1868 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1869 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
1870 vm
['vim_image_id'] = image_id
1872 #create flavor at vim in case it not exist
1873 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1874 if flavor_dict
['extended']!=None:
1875 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1876 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
1877 vm
['vim_flavor_id'] = flavor_id
1879 myVMDict
['imageRef'] = vm
['vim_image_id']
1880 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1881 myVMDict
['networks'] = []
1882 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
1883 for iface
in vm
['interfaces']:
1885 if iface
['type']=="data":
1886 netDict
['type'] = iface
['model']
1887 elif "model" in iface
and iface
["model"]!=None:
1888 netDict
['model']=iface
['model']
1889 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1890 #discover type of interface looking at flavor
1891 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1892 for flavor_iface
in numa
.get('interfaces',[]):
1893 if flavor_iface
.get('name') == iface
['internal_name']:
1894 if flavor_iface
['dedicated'] == 'yes':
1895 netDict
['type']="PF" #passthrough
1896 elif flavor_iface
['dedicated'] == 'no':
1897 netDict
['type']="VF" #siov
1898 elif flavor_iface
['dedicated'] == 'yes:sriov':
1899 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1900 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1902 netDict
["use"]=iface
['type']
1903 if netDict
["use"]=="data" and not netDict
.get("type"):
1904 #print "netDict", netDict
1905 #print "iface", iface
1906 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'])
1907 if flavor_dict
.get('extended')==None:
1908 raise NfvoException(e_text
+ "After database migration some information is not available. \
1909 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1911 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1912 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1913 netDict
["type"]="virtual"
1914 if "vpci" in iface
and iface
["vpci"] is not None:
1915 netDict
['vpci'] = iface
['vpci']
1916 if "mac" in iface
and iface
["mac"] is not None:
1917 netDict
['mac_address'] = iface
['mac']
1918 netDict
['name'] = iface
['internal_name']
1919 if iface
['net_id'] is None:
1920 for vnf_iface
in sce_vnf
["interfaces"]:
1923 if vnf_iface
['interface_id']==iface
['uuid']:
1924 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
1927 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1928 #skip bridge ifaces not connected to any net
1929 #if 'net_id' not in netDict or netDict['net_id']==None:
1931 myVMDict
['networks'].append(netDict
)
1932 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1933 #print myVMDict['name']
1934 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1935 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1936 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1937 vm_id
= vim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1938 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'], cloud_config
= cloud_config
)
1939 vm
['vim_id'] = vm_id
1940 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1941 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1942 for net
in myVMDict
['networks']:
1944 for iface
in vm
['interfaces']:
1945 if net
["name"]==iface
["internal_name"]:
1946 iface
["vim_id"]=net
["vim_id"]
1948 logger
.debug("create_instance Deployment done")
1949 print yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)
1950 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1951 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
1952 return mydb
.get_instance_scenario(instance_id
)
1953 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
1954 message
= rollback(mydb
, myvims
, rollbackList
)
1955 if isinstance(e
, db_base_Exception
):
1956 error_text
= "database Exception"
1957 elif isinstance(e
, vimconn
.vimconnException
):
1958 error_text
= "VIM Exception"
1960 error_text
= "Exception"
1961 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1962 #logger.error("create_instance: %s", error_text)
1963 raise NfvoException(error_text
, e
.http_code
)
1965 def delete_instance(mydb
, tenant_id
, instance_id
):
1966 #print "Checking that the instance_id exists and getting the instance dictionary"
1967 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
1968 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
1969 tenant_id
= instanceDict
["tenant_id"]
1970 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1972 vims
= get_vim(mydb
, tenant_id
, instanceDict
['datacenter_id'])
1974 logger
.error("!!!!!! nfvo.delete_instance() datacenter not found!!!!")
1977 myvim
= vims
.values()[0]
1978 except NfvoException
as e
:
1979 logger
.error("!!!!!! nfvo.delete_instance() datacenter Exception!!!! " + str(e
))
1983 #1. Delete from Database
1985 #result,c = mydb.delete_row_by_id('instance_scenarios', instance_id, nfvo_tenant)
1986 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
1990 error_msg
= "Not possible to delete VIM VMs and networks. Datacenter not found at database!!!"
1996 for sce_vnf
in instanceDict
['vnfs']:
1999 for vm
in sce_vnf
['vms']:
2001 myvim
.delete_vminstance(vm
['vim_vm_id'])
2002 except vimconn
.vimconnNotFoundException
as e
:
2003 error_msg
+="\n VM id={} not found at VIM".format(vm
['vim_vm_id'])
2004 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2005 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2006 except vimconn
.vimconnException
as e
:
2007 error_msg
+="\n Error: " + e
.http_code
+ " VM id=" + vm
['vim_vm_id']
2008 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s': %s",
2009 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2013 for net
in instanceDict
['nets']:
2015 continue #skip not created nets
2019 myvim
.delete_network(net
['vim_net_id'])
2020 except vimconn
.vimconnNotFoundException
as e
:
2021 error_msg
+="\n NET id={} not found at VIM".format(net
['vim_net_id'])
2022 logger
.warn("NET '%s', VIM id '%s', from VNF_id '%s' not found",
2023 net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'])
2024 except vimconn
.vimconnException
as e
:
2025 error_msg
+="\n Error: " + e
.http_code
+ " Net id=" + net
['vim_vm_id']
2026 logger
.error("Error %d deleting NET '%s', VIM id '%s', from VNF_id '%s': %s",
2027 e
.http_code
, net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'], str(e
))
2028 if len(error_msg
)>0:
2029 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2031 return 'instance ' + message
+ ' deleted'
2033 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2034 '''Refreshes a scenario instance. It modifies instanceDict'''
2036 - 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
2039 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2040 #print "nfvo.refresh_instance begins"
2041 #print json.dumps(instanceDict, indent=4)
2043 #print "Getting the VIM URL and the VIM tenant_id"
2044 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2046 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2047 myvim
= vims
.values()[0]
2049 # 1. Getting VIM vm and net list
2050 vms_updated
= [] #List of VM instance uuids in openmano that were updated
2053 for sce_vnf
in instanceDict
['vnfs']:
2054 for vm
in sce_vnf
['vms']:
2055 vm_list
.append(vm
['vim_vm_id'])
2056 vms_notupdated
.append(vm
["uuid"])
2058 nets_updated
= [] #List of VM instance uuids in openmano that were updated
2061 for net
in instanceDict
['nets']:
2062 net_list
.append(net
['vim_net_id'])
2063 nets_notupdated
.append(net
["uuid"])
2066 # 1. Getting the status of all VMs
2067 vm_dict
= myvim
.refresh_vms_status(vm_list
)
2069 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2070 for sce_vnf
in instanceDict
['vnfs']:
2071 for vm
in sce_vnf
['vms']:
2072 vm_id
= vm
['vim_vm_id']
2073 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
2074 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2075 has_mgmt_iface
= False
2076 for iface
in vm
["interfaces"]:
2077 if iface
["type"]=="mgmt":
2078 has_mgmt_iface
= True
2079 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
2080 vm_dict
[vm_id
]['status'] = "ACTIVE"
2081 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'):
2082 vm
['status'] = vm_dict
[vm_id
]['status']
2083 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
2084 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
2085 # 2.1. Update in openmano DB the VMs whose status changed
2087 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
2088 vms_notupdated
.remove(vm
["uuid"])
2090 vms_updated
.append(vm
["uuid"])
2091 except db_base_Exception
as e
:
2092 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2093 # 2.2. Update in openmano DB the interface VMs
2094 for interface
in interfaces
:
2095 #translate from vim_net_id to instance_net_id
2097 for net
in instanceDict
['nets']:
2098 if net
["vim_net_id"] == interface
["vim_net_id"]:
2099 network_id
= net
["uuid"]
2103 del interface
["vim_net_id"]
2105 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
2106 except db_base_Exception
as e
:
2107 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
2109 # 3. Getting the status of all nets
2110 net_dict
= myvim
.refresh_nets_status(net_list
)
2112 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2113 # TODO: update nets inside a vnf
2114 for net
in instanceDict
['nets']:
2115 net_id
= net
['vim_net_id']
2116 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'):
2117 net
['status'] = net_dict
[net_id
]['status']
2118 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
2119 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
2120 # 5.1. Update in openmano DB the nets whose status changed
2122 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
2123 nets_notupdated
.remove(net
["uuid"])
2125 nets_updated
.append(net
["uuid"])
2126 except db_base_Exception
as e
:
2127 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2128 except vimconn
.vimconnException
as e
:
2129 #logger.error("VIM exception %s %s", type(e).__name__, str(e))
2130 raise NfvoException(str(e
), e
.http_code
)
2132 # Returns appropriate output
2133 #print "nfvo.refresh_instance finishes"
2134 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2135 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
2136 instance_id
= instanceDict
['uuid']
2137 if len(vms_notupdated
)+len(nets_notupdated
)>0:
2138 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
2139 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
2141 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2143 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2144 #print "Checking that the instance_id exists and getting the instance dictionary"
2145 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2146 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2148 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2149 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2151 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2152 myvim
= vims
.values()[0]
2155 input_vnfs
= action_dict
.pop("vnfs", [])
2156 input_vms
= action_dict
.pop("vms", [])
2157 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2161 for sce_vnf
in instanceDict
['vnfs']:
2162 for vm
in sce_vnf
['vms']:
2163 if not action_over_all
:
2164 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2165 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2168 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2169 if "console" in action_dict
:
2170 if not global_config
["http_console_proxy"]:
2171 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2172 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2173 protocol
=data
["protocol"],
2174 ip
= data
["server"],
2175 port
= data
["port"],
2176 suffix
= data
["suffix"]),
2180 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2181 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2182 "description": "this console is only reachable by local interface",
2187 #print "console data", data
2189 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2190 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2191 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2192 protocol
=data
["protocol"],
2193 ip
= global_config
["http_console_host"],
2194 port
= console_thread
.port
,
2195 suffix
= data
["suffix"]),
2199 except NfvoException
as e
:
2200 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2204 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2206 except vimconn
.vimconnException
as e
:
2207 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2210 if vm_ok
==0: #all goes wrong
2215 def create_or_use_console_proxy_thread(console_server
, console_port
):
2216 #look for a non-used port
2217 console_thread_key
= console_server
+ ":" + str(console_port
)
2218 if console_thread_key
in global_config
["console_thread"]:
2219 #global_config["console_thread"][console_thread_key].start_timeout()
2220 return global_config
["console_thread"][console_thread_key
]
2222 for port
in global_config
["console_port_iterator"]():
2223 #print "create_or_use_console_proxy_thread() port:", port
2224 if port
in global_config
["console_ports"]:
2227 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2229 global_config
["console_thread"][console_thread_key
] = clithread
2230 global_config
["console_ports"][port
] = console_thread_key
2232 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2233 #port used, try with onoher
2235 except cli
.ConsoleProxyException
as e
:
2236 raise NfvoException(str(e
), HTTP_Bad_Request
)
2237 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2239 def check_tenant(mydb
, tenant_id
):
2240 '''check that tenant exists at database'''
2241 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2243 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2246 def new_tenant(mydb
, tenant_dict
):
2247 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2250 def delete_tenant(mydb
, tenant
):
2251 #get nfvo_tenant info
2253 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2254 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2255 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2257 def new_datacenter(mydb
, datacenter_descriptor
):
2258 if "config" in datacenter_descriptor
:
2259 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2260 #Check that datacenter-type is correct
2261 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2264 module
= "vimconn_" + datacenter_type
2265 module_info
= imp
.find_module(module
)
2266 except (IOError, ImportError):
2267 if module_info
and module_info
[0]:
2268 file.close(module_info
[0])
2269 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2271 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2272 return datacenter_id
2274 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2275 #obtain data, check that only one exist
2276 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2278 datacenter_id
= datacenter
['uuid']
2279 where
={'uuid': datacenter
['uuid']}
2280 if "config" in datacenter_descriptor
:
2281 if datacenter_descriptor
['config']!=None:
2283 new_config_dict
= datacenter_descriptor
["config"]
2286 for k
in new_config_dict
:
2287 if new_config_dict
[k
]==None:
2290 config_dict
= yaml
.load(datacenter
["config"])
2291 config_dict
.update(new_config_dict
)
2295 except Exception as e
:
2296 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2297 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2298 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2299 return datacenter_id
2301 def delete_datacenter(mydb
, datacenter
):
2302 #get nfvo_tenant info
2303 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2304 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2305 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2307 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None):
2308 #get datacenter info
2309 if utils
.check_valid_uuid(datacenter
):
2310 vims
= get_vim(mydb
, datacenter_id
=datacenter
, vim_tenant_name
=vim_tenant_name
, vim_user
=vim_username
, vim_passwd
=vim_password
)
2312 vims
= get_vim(mydb
, datacenter_name
=datacenter
, vim_tenant_name
=vim_tenant_name
, vim_user
=vim_username
, vim_passwd
=vim_password
)
2314 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2316 #print "nfvo.datacenter_action() error. Several datacenters found"
2317 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2319 datacenter_id
=vims
.keys()[0]
2320 myvim
=vims
[datacenter_id
]
2321 datacenter_name
=myvim
["name"]
2323 create_vim_tenant
=True if vim_tenant_id
==None and vim_tenant_name
==None else False
2325 #get nfvo_tenant info
2326 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2327 if vim_tenant_name
==None:
2328 vim_tenant_name
=tenant_dict
['name']
2330 #check that this association does not exist before
2331 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2332 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2333 if len(tenants_datacenters
)>0:
2334 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2336 vim_tenant_id_exist_atdb
=False
2337 if not create_vim_tenant
:
2338 where_
={"datacenter_id": datacenter_id
}
2339 if vim_tenant_id
!=None:
2340 where_
["vim_tenant_id"] = vim_tenant_id
2341 if vim_tenant_name
!=None:
2342 where_
["vim_tenant_name"] = vim_tenant_name
2343 #check if vim_tenant_id is already at database
2344 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2345 if len(datacenter_tenants_dict
)>=1:
2346 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2347 vim_tenant_id_exist_atdb
=True
2348 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2350 datacenter_tenants_dict
= {}
2351 #insert at table datacenter_tenants
2352 else: #if vim_tenant_id==None:
2353 #create tenant at VIM if not provided
2355 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2356 except vimconn
.vimconnException
as e
:
2357 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2358 datacenter_tenants_dict
= {}
2359 datacenter_tenants_dict
["created"]="true"
2361 #fill datacenter_tenants table
2362 if not vim_tenant_id_exist_atdb
:
2363 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2364 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2365 datacenter_tenants_dict
["user"] = vim_username
2366 datacenter_tenants_dict
["passwd"] = vim_password
2367 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2368 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2369 datacenter_tenants_dict
["uuid"] = id_
2371 #fill tenants_datacenters table
2372 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2373 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2374 return datacenter_id
2376 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2377 #get datacenter info
2378 if utils
.check_valid_uuid(datacenter
):
2379 vims
= get_vim(mydb
, datacenter_id
=datacenter
)
2381 vims
= get_vim(mydb
, datacenter_name
=datacenter
)
2383 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2385 #print "nfvo.datacenter_action() error. Several datacenters found"
2386 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2387 datacenter_id
=vims
.keys()[0]
2388 myvim
=vims
[datacenter_id
]
2390 #get nfvo_tenant info
2391 if not tenant_id
or tenant_id
=="any":
2394 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2395 tenant_uuid
= tenant_dict
['uuid']
2397 #check that this association exist before
2398 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2400 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2401 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2402 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2403 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2405 #delete this association
2406 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2408 #get vim_tenant info and deletes
2410 for tenant_datacenter_item
in tenant_datacenter_list
:
2411 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2412 #try to delete vim:tenant
2414 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2415 if vim_tenant_dict
['created']=='true':
2416 #delete tenant at VIM if created by NFVO
2418 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2419 except vimconn
.vimconnException
as e
:
2420 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2421 logger
.warn(warning
)
2422 except db_base_Exception
as e
:
2423 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2424 pass #the error will be caused because dependencies, vim_tenant can not be deleted
2426 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2428 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2430 #get datacenter info
2431 if utils
.check_valid_uuid(datacenter
):
2432 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2434 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2436 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2438 #print "nfvo.datacenter_action() error. Several datacenters found"
2439 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2440 datacenter_id
=vims
.keys()[0]
2441 myvim
=vims
[datacenter_id
]
2443 if 'net-update' in action_dict
:
2445 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2447 except vimconn
.vimconnException
as e
:
2448 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2449 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2450 #update nets Change from VIM format to NFVO format
2453 net_nfvo
={'datacenter_id': datacenter_id
}
2454 net_nfvo
['name'] = net
['name']
2455 #net_nfvo['description']= net['name']
2456 net_nfvo
['vim_net_id'] = net
['id']
2457 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2458 net_nfvo
['shared'] = net
['shared']
2459 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2460 net_list
.append(net_nfvo
)
2461 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2462 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2464 elif 'net-edit' in action_dict
:
2465 net
= action_dict
['net-edit'].pop('net')
2466 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2467 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2468 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2470 elif 'net-delete' in action_dict
:
2471 net
= action_dict
['net-deelte'].get('net')
2472 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2473 result
= mydb
.delete_row(FROM
='datacenter_nets',
2474 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2478 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2480 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2481 #get datacenter info
2482 if utils
.check_valid_uuid(datacenter
):
2483 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2485 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2487 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2489 #print "nfvo.datacenter_action() error. Several datacenters found"
2490 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2491 datacenter_id
=vims
.keys()[0]
2493 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2494 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2495 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2498 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2499 #get datacenter info
2500 if utils
.check_valid_uuid(datacenter
):
2501 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2503 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2505 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2507 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2508 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2509 datacenter_id
=vims
.keys()[0]
2510 myvim
=vims
[datacenter_id
]
2513 action_dict
= action_dict
["netmap"]
2514 if 'vim_id' in action_dict
:
2515 filter_dict
["id"] = action_dict
['vim_id']
2516 if 'vim_name' in action_dict
:
2517 filter_dict
["name"] = action_dict
['vim_name']
2519 filter_dict
["shared"] = True
2522 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
2523 except vimconn
.vimconnException
as e
:
2524 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
2525 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2526 if len(vim_nets
)>1 and action_dict
:
2527 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
2528 elif len(vim_nets
)==0: # and action_dict:
2529 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
2531 for net
in vim_nets
:
2532 net_nfvo
={'datacenter_id': datacenter_id
}
2533 if action_dict
and "name" in action_dict
:
2534 net_nfvo
['name'] = action_dict
['name']
2536 net_nfvo
['name'] = net
['name']
2537 #net_nfvo['description']= net['name']
2538 net_nfvo
['vim_net_id'] = net
['id']
2539 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2540 net_nfvo
['shared'] = net
['shared']
2541 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2543 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2544 net_nfvo
["status"] = "OK"
2545 net_nfvo
["uuid"] = net_id
2546 except db_base_Exception
as e
:
2550 net_nfvo
["status"] = "FAIL: " + str(e
)
2551 net_list
.append(net_nfvo
)
2554 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2555 #get datacenter info
2556 if utils
.check_valid_uuid(datacenter
):
2557 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2559 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2561 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2563 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2564 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2565 datacenter_id
=vims
.keys()[0]
2566 myvim
=vims
[datacenter_id
]
2569 if utils
.check_valid_uuid(name
):
2570 filter_dict
["id"] = name
2572 filter_dict
["name"] = name
2574 if item
=="networks":
2575 #filter_dict['tenant_id'] = myvim['tenant_id']
2576 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2577 elif item
=="tenants":
2578 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2580 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2581 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
2582 if name
and len(content
)==1:
2583 return {item
[:-1]: content
[0]}
2584 elif name
and len(content
)==0:
2585 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
2588 return {item
: content
}
2589 except vimconn
.vimconnException
as e
:
2590 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
2591 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
2593 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
2594 #get datacenter info
2595 if tenant_id
== "any":
2598 if utils
.check_valid_uuid(datacenter
):
2599 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2601 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2603 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2605 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2606 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2607 datacenter_id
=vims
.keys()[0]
2608 myvim
=vims
[datacenter_id
]
2610 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2611 logger
.debug("vim_action_delete vim response: " + str(content
))
2612 items
= content
.values()[0]
2613 if type(items
)==list and len(items
)==0:
2614 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
2615 elif type(items
)==list and len(items
)>1:
2616 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
2617 else: # it is a dict
2618 item_id
= items
["id"]
2619 item_name
= str(items
.get("name"))
2622 if item
=="networks":
2623 content
= myvim
.delete_network(item_id
)
2624 elif item
=="tenants":
2625 content
= myvim
.delete_tenant(item_id
)
2627 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2628 except vimconn
.vimconnException
as e
:
2629 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
2630 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
2632 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
2634 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2635 #get datacenter info
2636 print "vim_action_create descriptor", descriptor
2637 if tenant_id
== "any":
2640 if utils
.check_valid_uuid(datacenter
):
2641 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2643 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2645 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2647 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2648 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2649 datacenter_id
=vims
.keys()[0]
2650 myvim
=vims
[datacenter_id
]
2653 if item
=="networks":
2654 net
= descriptor
["network"]
2655 net_name
= net
.pop("name")
2656 net_type
= net
.pop("type", "bridge")
2657 net_public
= net
.pop("shared", False)
2658 net_ipprofile
= net
.pop("ip_profile", None)
2659 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, **net
)
2660 elif item
=="tenants":
2661 tenant
= descriptor
["tenant"]
2662 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2664 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2665 except vimconn
.vimconnException
as e
:
2666 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
2668 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)