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 nfvo_db
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
41 global vimconn_imported
44 vimconn_imported
={} #dictionary with VIM type as key, loaded module as value
45 logger
= logging
.getLogger('mano.nfvo')
47 class NfvoException(Exception):
48 def __init__(self
, message
, http_code
):
49 self
.http_code
= http_code
50 Exception.__init
__(self
, message
)
53 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
55 return result, content:
56 <0, error_text upon error
57 nb_records, flavor_list on success
60 WHERE_dict
['vnf_id'] = vnf_id
61 if nfvo_tenant
is not None:
62 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
64 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
65 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
66 result
, content
= mydb
.get_table(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
68 print "nfvo.get_flavorlist error %d %s" % (result
, content
)
69 return -result
, content
70 print "get_flavor_list result:", result
71 print "get_flavor_list content:", content
73 for flavor
in content
:
74 flavorList
.append(flavor
['flavor_id'])
75 return result
, flavorList
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 result
, content
= mydb
.get_table(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
91 print "nfvo.get_imagelist error %d %s" % (result
, content
)
92 return -result
, content
93 print "get_image_list result:", result
94 print "get_image_list content:", content
97 imageList
.append(image
['image_id'])
98 return result
, imageList
100 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, vim_tenant
=None):
101 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
102 return result, content:
103 <0, error_text upon error
104 NUMBER, dictionary with datacenter_id: vim_class with these keys:
105 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
108 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
109 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
110 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
111 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
112 if nfvo_tenant
or vim_tenant
:
113 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'
114 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
115 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
118 from_
= 'datacenters as d'
119 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
120 result
, content
= mydb
.get_table(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
122 print "nfvo.get_vim error %d %s" % (result
, content
)
123 return result
, content
125 # print "nfvo.get_vim not found a valid VIM with the input params " + str(WHERE_dict)
126 # return -HTTP_Not_Found, "datacenter not found for " + str(WHERE_dict)
130 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
131 if vim
["config"] != None:
132 extra
.update(yaml
.load(vim
["config"]))
133 if vim
["type"] not in vimconn_imported
:
136 module
= "vimconn_" + vim
["type"]
137 module_info
= imp
.find_module(module
)
138 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
139 vimconn_imported
[vim
["type"]] = vim_conn
140 except (IOError, ImportError) as e
:
141 if module_info
and module_info
[0]:
142 file.close(module_info
[0])
143 print "Cannot open VIM module '%s.py'; %s: %s" % ( module
, type(e
).__name
__, str(e
))
144 return -HTTP_Bad_Request
, "Unknown vim type %s" % vim
["type"]
148 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
149 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
150 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
151 tenant_id
=vim
.get('vim_tenant_id'), tenant_name
=vim
.get('vim_tenant_name'),
152 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
153 user
=vim
.get('user'), passwd
=vim
.get('passwd'),
156 except Exception as e
:
157 return -HTTP_Internal_Server_Error
, "Error at VIM %s; %s: %s" % ( vim
["type"], type(e
).__name
__, str(e
))
158 return len(vim_dict
), vim_dict
160 def rollback(mydb
, vims
, rollback_list
):
162 #delete things by reverse order
163 for i
in range(len(rollback_list
)-1, -1, -1):
164 item
= rollback_list
[i
]
165 if item
["where"]=="vim":
166 if item
["vim_id"] not in vims
:
168 vim
=vims
[ item
["vim_id"] ]
170 if item
["what"]=="image":
171 vim
.delete_image(item
["uuid"])
172 result
, message
= mydb
.delete_row_by_dict(FROM
="datacenters_images", WEHRE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
174 logger
.error("Error in rollback. Not possible to delete image '%s' from DB.dacenters_images. Message: %s", item
["uuid"],message
)
175 elif item
["what"]=="flavor":
176 vim
.delete_flavor(item
["uuid"])
177 result
, message
= mydb
.delete_row_by_dict(FROM
="datacenters_flavos", WEHRE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
179 logger
.error("Error in rollback. Not possible to delete flavor '%s' from DB.dacenters_flavors. Message: %s", item
["uuid"],message
)
180 elif item
["what"]=="network":
181 vim
.delete_network(item
["uuid"])
182 elif item
["what"]=="vm":
183 vim
.delete_vminstance(item
["uuid"])
184 except vimconn
.vimconnException
as e
:
185 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
186 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
189 if item
["what"]=="image":
190 result
, message
= mydb
.delete_row_by_dict(FROM
="images", WEHRE
={"uuid": item
["uuid"]})
192 logger
.error("Error in rollback. Not possible to delete image '%s' from DB.images. Message: %s", item
["uuid"], message
)
193 undeleted_items
.append("image %s" % (item
["uuid"]))
194 elif item
["what"]=="flavor":
195 result
, message
= mydb
.delete_row_by_dict(FROM
="flavors", WEHRE
={"uuid": item
["uuid"]})
197 logger
.error("Error in rollback. Not possible to delete flavor '%s' from DB.flavors. Message: %s", item
["uuid"], message
)
198 undeleted_items
.append("flavor %s" % (item
["uuid"]))
199 if len(undeleted_items
)==0:
200 return True," Rollback successful."
202 return False," Rollback fails to delete: " + str(undeleted_items
)
204 def check_vnf_descriptor(vnf_descriptor
):
206 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
208 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
210 #dataplane interfaces
211 for numa
in vnfc
.get("numas",() ):
212 for interface
in numa
.get("interfaces",()):
213 if interface
["name"] in name_list
:
214 return -HTTP_Bad_Request
, "Error at vnf:VNFC[name:'%s']:numas:interfaces:name, interface name '%s' already used in this VNFC" %(vnfc
["name"], interface
["name"])
215 name_list
.append( interface
["name"] )
217 for interface
in vnfc
.get("bridge-ifaces",() ):
218 if interface
["name"] in name_list
:
219 return -HTTP_Bad_Request
, "Error at vnf:VNFC[name:'%s']:bridge-ifaces:name, interface name '%s' already used in this VNFC" %(vnfc
["name"], interface
["name"])
220 name_list
.append( interface
["name"] )
221 vnfc_interfaces
[ vnfc
["name"] ] = name_list
223 #check if the info in external_connections matches with the one in the vnfcs
225 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
226 if external_connection
["name"] in name_list
:
227 return -HTTP_Bad_Request
, "Error at vnf:external-connections:name, value '%s' already used as an external-connection" %(external_connection
["name"])
228 name_list
.append(external_connection
["name"])
229 if external_connection
["VNFC"] not in vnfc_interfaces
:
230 return -HTTP_Bad_Request
, "Error at vnf:external-connections[name:'%s']:VNFC, value '%s' does not match any VNFC" %(external_connection
["name"], external_connection
["VNFC"])
231 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
232 return -HTTP_Bad_Request
, "Error at vnf:external-connections[name:'%s']:local_iface_name, value '%s' does not match any interface of this VNFC" %(external_connection
["name"], external_connection
["local_iface_name"])
234 #check if the info in internal_connections matches with the one in the vnfcs
236 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
237 if internal_connection
["name"] in name_list
:
238 return -HTTP_Bad_Request
, "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection" %(internal_connection
["name"])
239 name_list
.append(internal_connection
["name"])
240 #We should check that internal-connections of type "ptp" have only 2 elements
241 if len(internal_connection
["elements"])>2 and internal_connection
["type"] == "ptp":
242 return -HTTP_Bad_Request
, "Error at vnf:internal-connections[name:'%s']:elements, size must be 2 for a type:'ptp'" %(internal_connection
["name"])
243 for port
in internal_connection
["elements"]:
244 if port
["VNFC"] not in vnfc_interfaces
:
245 return -HTTP_Bad_Request
, "Error at vnf:internal-connections[name:'%s']:elements[]:VNFC, value '%s' does not match any VNFC" %(internal_connection
["name"], port
["VNFC"])
246 if port
["local_iface_name"] not in vnfc_interfaces
[ port
["VNFC"] ]:
247 return -HTTP_Bad_Request
, "Error at vnf:internal-connections[name:'%s']:elements[]:local_iface_name, value '%s' does not match any interface of this VNFC" %(internal_connection
["name"], port
["local_iface_name"])
252 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
254 if only_create_at_vim
:
255 image_mano_id
= image_dict
['uuid']
257 res
,content
= mydb
.get_table(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
259 image_mano_id
= content
[0]['uuid']
264 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
265 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None)
267 res
,content
= mydb
.new_row('images', temp_image_dict
, tenant_id
=None, add_uuid
=True)
269 image_mano_id
= content
270 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
272 return res
if res
<0 else -1, content
273 #create image at every vim
274 for vim_id
,vim
in vims
.iteritems():
275 image_created
="false"
277 res_db
,image_db
= mydb
.get_table(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
279 return res_db
, image_db
280 #look at VIM if this image exist
282 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
283 except vimconn
.vimconnNotFoundException
as e
:
284 #Create the image in VIM
286 image_vim_id
= vim
.new_image(image_dict
)
287 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
289 except vimconn
.vimconnException
as e
:
291 logger
.error("Error creating image at VIM: %s", str(e
))
292 return -e
.http_code
, str(e
)
293 image_vim_id
= str(e
)
294 logger
.warn("Error creating image at VIM: %s", str(e
))
296 except vimconn
.vimconnException
as e
:
297 logger
.warn("Error contacting VIM to know if the image exist at VIM: %s", str(e
))
298 image_vim_id
= str(e
)
300 #if reach here the image has been create or exist
302 #add new vim_id at datacenters_images
303 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
304 elif image_db
[0]["vim_id"]!=image_vim_id
:
305 #modify existing vim_id at datacenters_images
306 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
308 return 1, image_vim_id
if only_create_at_vim
else image_mano_id
310 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
311 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
312 'ram':flavor_dict
.get('ram'),
313 'vcpus':flavor_dict
.get('vcpus'),
315 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
316 del flavor_dict
['extended']
317 if 'extended' in flavor_dict
:
318 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
320 #look if flavor exist
321 if only_create_at_vim
:
322 flavor_mano_id
= flavor_dict
['uuid']
324 res
,content
= mydb
.get_table(FROM
="flavors", WHERE
=temp_flavor_dict
)
326 flavor_mano_id
= content
[0]['uuid']
331 #create one by one the images of aditional disks
332 dev_image_list
=[] #list of images
333 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
335 for device
in flavor_dict
['extended'].get('devices',[]):
336 if "image" not in device
:
338 image_dict
={'location':device
['image'], 'name':flavor_dict
['name']+str(dev_nb
)+"-img", 'description':flavor_dict
.get('description')}
339 image_metadata_dict
= device
.get('image metadata', None)
340 image_metadata_str
= None
341 if image_metadata_dict
!= None:
342 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
343 image_dict
['metadata']=image_metadata_str
344 res
, image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
346 return res
, image_id
+ rollback(mydb
, vims
, rollback_list
)[1]
347 print "Additional disk image id for VNFC %s: %s" % (flavor_dict
['name']+str(dev_nb
)+"-img", image_id
)
348 dev_image_list
.append(image_id
)
350 temp_flavor_dict
['name'] = flavor_dict
['name']
351 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
352 res
,content
= mydb
.new_row('flavors', temp_flavor_dict
, tenant_id
=None, add_uuid
=True)
354 flavor_mano_id
= content
355 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
357 return res
if res
<0 else -1, content
358 #create flavor at every vim
359 if 'uuid' in flavor_dict
:
360 del flavor_dict
['uuid']
362 for vim_id
,vim
in vims
.items():
363 flavor_created
="false"
365 res_db
,flavor_db
= mydb
.get_table(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
367 return res_db
, flavor_db
368 #look at VIM if this flavor exist SKIPPED
369 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
371 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
375 #Create the flavor in VIM
376 #Translate images at devices from MANO id to VIM id
378 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
379 #make a copy of original devices
381 for device
in flavor_dict
["extended"].get("devices",[]):
384 devices_original
.append(dev
)
385 if 'image' in device
:
387 if 'image metadata' in device
:
388 del device
['image metadata']
390 for index
in range(0,len(devices_original
)) :
391 device
=devices_original
[index
]
392 if "image" not in device
:
394 image_dict
={'location':device
['image'], 'name':flavor_dict
['name']+str(dev_nb
)+"-img", 'description':flavor_dict
.get('description')}
395 image_metadata_dict
= device
.get('image metadata', None)
396 image_metadata_str
= None
397 if image_metadata_dict
!= None:
398 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
399 image_dict
['metadata']=image_metadata_str
400 r
,image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False)
402 print "Error creating device image for flavor: %s." %image
_mano
_id
403 error_text
= image_mano_id
406 image_dict
["uuid"]=image_mano_id
407 r
,image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True)
409 print "Error creating device image for flavor at VIM: %s." %image
_vim
_id
410 error_text
= image_vim_id
413 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
420 #check that this vim_id exist in VIM, if not create
421 flavor_vim_id
=flavor_db
[0]["vim_id"]
423 vim
.get_flavor(flavor_vim_id
)
424 continue #flavor exist
425 except vimconn
.vimconnException
:
427 #create flavor at vim
428 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
430 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
431 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
432 flavor_created
="true"
433 except vimconn
.vimconnException
as e
:
435 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
436 return -e
.http_code
, str(e
)
437 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
439 #if reach here the flavor has been create or exist
441 #add new vim_id at datacenters_flavors
442 mydb
.new_row('datacenters_flavors', {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
, 'created':flavor_created
})
443 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
444 #modify existing vim_id at datacenters_flavors
445 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
447 return 1, flavor_vim_id
if only_create_at_vim
else flavor_mano_id
449 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
452 # Step 1. Check the VNF descriptor
453 result
, message
= check_vnf_descriptor(vnf_descriptor
)
455 print "new_vnf error: %s" %message
456 return result
, message
458 # Step 2. Check tenant exist
459 if tenant_id
!= "any":
460 if not check_tenant(mydb
, tenant_id
):
461 print 'nfvo.new_vnf() tenant %s not found' % tenant_id
462 return -HTTP_Not_Found
, 'Tenant %s not found' % tenant_id
463 if "tenant_id" in vnf_descriptor
["vnf"]:
464 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
465 print "nfvo.new_vnf() tenant '%s' not found" % tenant_id
466 return -HTTP_Unauthorized
, "VNF can not have a different tenant owner '%s', must be '%s'" %(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
)
468 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
469 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
470 result
, vims
= get_vim(mydb
, tenant_id
)
472 print "nfvo.new_vnf() error. Datacenter not found"
477 # Step 4. Review the descriptor and add missing fields
478 #print vnf_descriptor
479 print "Refactoring VNF descriptor with fields: description, public (default: true)"
480 vnf_name
= vnf_descriptor
['vnf']['name']
481 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
482 if "physical" in vnf_descriptor
['vnf']:
483 del vnf_descriptor
['vnf']['physical']
484 #print vnf_descriptor
485 # Step 5. Check internal connections
486 # TODO: to be moved to step 1????
487 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
488 for ic
in internal_connections
:
489 if len(ic
['elements'])>2 and ic
['type']=='ptp':
490 return -HTTP_Bad_Request
, "Mismatch 'type':'ptp' with %d elements at 'vnf':'internal-conections'['name':'%s']. Change 'type' to 'data'" %(len(ic
), ic
['name'])
491 elif len(ic
['elements'])==2 and ic
['type']=='data':
492 return -HTTP_Bad_Request
, "Mismatch 'type':'data' with 2 elements at 'vnf':'internal-conections'['name':'%s']. Change 'type' to 'ptp'" %(ic
['name'])
494 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
495 print 'BEGIN creation of VNF "%s"' % vnf_name
496 print "VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC']))
498 #For each VNFC, we add it to the VNFCDict and we create a flavor.
499 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
500 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
503 print "Creating additional disk images and new flavors in the VIM for each VNFC"
504 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
506 VNFCitem
["name"] = vnfc
['name']
507 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
509 print "Flavor name: %s. Description: %s" % (VNFCitem
["name"]+"-flv", VNFCitem
["description"])
512 myflavorDict
["name"] = vnfc
['name']+"-flv"
513 myflavorDict
["description"] = VNFCitem
["description"]
514 myflavorDict
["ram"] = vnfc
.get("ram", 0)
515 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
516 myflavorDict
["disk"] = vnfc
.get("disk", 1)
517 myflavorDict
["extended"] = {}
519 devices
= vnfc
.get("devices")
521 myflavorDict
["extended"]["devices"] = devices
524 # 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
525 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
527 # Previous code has been commented
528 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
529 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
530 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
531 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
533 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
535 # print "Error creating flavor: unknown processor model. Rollback successful."
536 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
538 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
539 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
541 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
542 myflavorDict
['extended']['numas'] = vnfc
['numas']
546 # Step 6.2 New flavors are created in the VIM
547 res
, flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
549 return res
, flavor_id
+ rollback(mydb
, vims
, rollback_list
)[1]
551 print "Flavor id for VNFC %s: %s" % (vnfc
['name'],flavor_id
)
552 VNFCitem
["flavor_id"] = flavor_id
553 VNFCDict
[vnfc
['name']] = VNFCitem
555 print "Creating new images in the VIM for each VNFC"
556 # Step 6.3 New images are created in the VIM
557 #For each VNFC, we must create the appropriate image.
558 #This "for" loop might be integrated with the previous one
559 #In case this integration is made, the VNFCDict might become a VNFClist.
560 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
561 print "Image name: %s. Description: %s" % (vnfc
['name']+"-img", VNFCDict
[vnfc
['name']]['description'])
562 image_dict
={'location':vnfc
['VNFC image'], 'name':vnfc
['name']+"-img", 'description':VNFCDict
[vnfc
['name']]['description']}
563 image_metadata_dict
= vnfc
.get('image metadata', None)
564 image_metadata_str
= None
565 if image_metadata_dict
is not None:
566 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
567 image_dict
['metadata']=image_metadata_str
568 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
569 res
, image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
571 return res
, image_id
+ rollback(mydb
, vims
, rollback_list
)[1]
572 print "Image id for VNFC %s: %s" % (vnfc
['name'],image_id
)
573 VNFCDict
[vnfc
['name']]["image_id"] = image_id
574 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
['VNFC image']
576 except KeyError as e
:
577 print "Error while creating a VNF. KeyError: " + str(e
)
578 _
, message
= rollback(mydb
, vims
, rollback_list
)
579 return -HTTP_Internal_Server_Error
, "Error while creating a VNF. KeyError " + str(e
) + "." + message
581 # Step 7. Storing the VNF descriptor in the repository
582 if "descriptor" not in vnf_descriptor
["vnf"]:
583 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
585 # Step 8. Adding the VNF to the NFVO DB
587 result
, vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
588 except KeyError as e
:
589 print "Error while creating a VNF. KeyError: " + str(e
)
590 _
, message
= rollback(mydb
, vims
, rollback_list
)
591 return -HTTP_Internal_Server_Error
, "Error while creating a VNF. KeyError " + str(e
) + "." + message
594 _
, message
= rollback(mydb
, vims
, rollback_list
)
595 return result
, vnf_id
+ "." + message
599 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
600 #check valid tenant_id
601 if tenant_id
!= "any" and not check_tenant(mydb
, tenant_id
):
602 print 'nfvo.get_vnf_id() tenant %s not found' % tenant_id
603 return -HTTP_Not_Found
, "Tenant '%s' not found" % tenant_id
606 if tenant_id
!= "any":
607 where_or
["tenant_id"] = tenant_id
608 where_or
["public"] = True
609 result
, content
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
611 print "nfvo.get_vnf_id() error %d %s" % (result
, content
)
612 return (result
, content
)
615 vnf_id
=content
["uuid"]
616 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
617 filtered_content
= dict( (k
,v
) for k
,v
in content
.iteritems() if k
in filter_keys
)
618 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
619 data
={'vnf' : filtered_content
}
621 result
,content
= mydb
.get_table(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
622 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description'),
623 WHERE
={'vnfs.uuid': vnf_id
} )
625 print "nfvo.get_vnf_id error %d %s" % (result
, content
)
626 return (result
, content
)
628 print "nfvo.get_vnf_id vnf '%s' not found" % vnf_id
629 return (-HTTP_Not_Found
, "vnf %s not found" % vnf_id
)
631 data
['vnf']['VNFC'] = content
633 result
,content
= mydb
.get_table(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
634 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
635 WHERE
={'vnfs.uuid': vnf_id
} )
637 print "nfvo.get_vnf_id error %d %s" % (result
, content
)
638 return (result
, content
)
641 data
['vnf']['nets'] = []
643 data
['vnf']['nets'] = content
645 result
,content
= mydb
.get_table(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
646 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
647 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
648 WHERE
={'vnfs.uuid': vnf_id
},
649 WHERE_NOT
={'interfaces.external_name': None} )
652 print "nfvo.get_vnf_id error %d %s" % (result
, content
)
653 return (result
, content
)
656 data
['vnf']['external-connections'] = []
658 data
['vnf']['external-connections'] = content
662 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
664 if tenant_id
!= "any":
665 if not check_tenant(mydb
, tenant_id
):
666 print 'nfvo.delete_vnf() tenant %s not found' % tenant_id
667 return -HTTP_Not_Found
, 'Tenant %s not found' % tenant_id
668 # Get the URL of the VIM from the nfvo_tenant and the datacenter
669 result
, vims
= get_vim(mydb
, tenant_id
)
671 print "nfvo.delete_vnf() error. Datacenter not found"
676 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
678 if tenant_id
!= "any":
679 where_or
["tenant_id"] = tenant_id
680 where_or
["public"] = True
681 result
, content
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
683 return result
, content
684 vnf_id
= content
["uuid"]
686 # "Getting the list of flavors and tenants of the VNF"
687 result
,flavorList
= get_flavorlist(mydb
, vnf_id
)
691 print "delete_vnf error. No flavors found for the VNF id '%s'" % vnf_id
693 result
,imageList
= get_imagelist(mydb
, vnf_id
)
694 print "imageList", imageList
698 print "delete_vnf error. No images found for the VNF id '%s'" % vnf_id
700 result
, content
= mydb
.delete_row('vnfs', vnf_id
, tenant_id
)
702 return -HTTP_Not_Found
, content
706 print "delete_vnf error",result
, content
707 return result
, content
710 for flavor
in flavorList
:
711 #check if flavor is used by other vnf
712 r
,c
= mydb
.get_table(FROM
='vms', WHERE
={'flavor_id':flavor
} )
714 print 'delete_vnf_error. Not possible to delete VIM flavor "%s". %s' % (flavor
,c
)
715 undeletedItems
.append("flavor "+ flavor
["flavor_id"])
717 print 'Flavor %s not deleted because it is being used by another VNF %s' %(flavor
,str(c
))
719 #flavor not used, must be deleted
721 r
,c
= mydb
.get_table(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
724 if flavor_vim
["datacenter_id"] not in vims
:
726 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
728 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
730 myvim
.delete_flavor(flavor_vim
["vim_id"])
731 except vimconn
.vimconnNotFoundException
as e
:
732 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
733 except vimconn
.vimconnException
as e
:
734 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
735 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
736 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
737 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
738 result
, content
= mydb
.delete_row('flavors', flavor
)
740 undeletedItems
.append("flavor %s" % flavor
)
742 for image
in imageList
:
743 #check if image is used by other vnf
744 r
,c
= mydb
.get_table(FROM
='vms', WHERE
={'image_id':image
} )
746 print 'delete_vnf_error. Not possible to delete VIM image "%s". %s' % (image
,c
)
747 undeletedItems
.append("image "+ image
["image_id"])
749 print 'Image %s not deleted because it is being used by another VNF %s' %(image
,str(c
))
751 #image not used, must be deleted
753 r
,c
= mydb
.get_table(FROM
='datacenters_images', WHERE
={'image_id':image
})
756 if image_vim
["datacenter_id"] not in vims
:
758 if image_vim
['created']=='false': #skip this image because not created by openmano
760 myvim
=vims
[ image_vim
["datacenter_id"] ]
762 myvim
.delete_image(image_vim
["vim_id"])
763 except vimconn
.vimconnNotFoundException
as e
:
764 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
765 except vimconn
.vimconnException
as e
:
766 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
767 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
768 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
769 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
770 result
, content
= mydb
.delete_row('images', image
)
772 undeletedItems
.append("image %s" % image
)
775 return 200, "delete_vnf error. Undeleted: %s" %(undeletedItems)
779 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
780 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
784 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
785 myvim
= vims
.values()[0]
786 result
,servers
= myvim
.get_hosts_info()
788 return result
, servers
789 topology
= {'name':myvim
['name'] , 'servers': servers
}
790 return result
, topology
792 def get_hosts(mydb
, nfvo_tenant_id
):
793 result
, vims
= get_vim(mydb
, nfvo_tenant_id
)
797 return -HTTP_Not_Found
, "No datacenter found"
798 myvim
= vims
.values()[0]
799 result
,hosts
= myvim
.get_hosts()
802 print '==================='
803 print 'hosts '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False)
805 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
807 server
={'name':host
['name'], 'vms':[]}
808 for vm
in host
['instances']:
809 #get internal name and model
810 r
,c
= mydb
.get_table(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
811 WHERE
={'vim_vm_id':vm
['id']} )
813 print "nfvo.get_hosts virtual machine at VIM (%s) not found at tidnfvo" % vm
['id']
816 print "nfvo.get_hosts virtual machine at VIM (%s) error %d %s" % (vm
['id'], r
, c
)
818 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
819 datacenter
['Datacenters'][0]['servers'].append(server
)
820 #return -400, "en construccion"
822 #print 'datacenters '+ json.dumps(datacenter, indent=4)
823 return result
, datacenter
825 def new_scenario(mydb
, tenant_id
, topo
):
827 # result, vims = get_vim(mydb, tenant_id)
829 # return result, vims
831 if tenant_id
!= "any":
832 if not check_tenant(mydb
, tenant_id
):
833 print 'nfvo.new_scenario() tenant %s not found' % tenant_id
834 return -HTTP_Not_Found
, 'Tenant %s not found' % tenant_id
835 if "tenant_id" in topo
:
836 if topo
["tenant_id"] != tenant_id
:
837 print "nfvo.new_scenario() tenant '%s' not found" % tenant_id
838 return -HTTP_Unauthorized
, "VNF can not have a different tenant owner '%s', must be '%s'" %(topo
["tenant_id"], tenant_id
)
842 #1.1: get VNFs and external_networks (other_nets).
844 other_nets
={} #external_networks, bridge_networks and data_networkds
845 nodes
= topo
['topology']['nodes']
846 for k
in nodes
.keys():
847 if nodes
[k
]['type'] == 'VNF':
849 vnfs
[k
]['ifaces'] = {}
850 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
851 other_nets
[k
] = nodes
[k
]
852 other_nets
[k
]['external']=True
853 elif nodes
[k
]['type'] == 'network':
854 other_nets
[k
] = nodes
[k
]
855 other_nets
[k
]['external']=False
858 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
859 for name
,vnf
in vnfs
.items():
862 error_pos
= "'topology':'nodes':'" + name
+ "'"
864 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
865 WHERE_
['uuid'] = vnf
['vnf_id']
866 if 'VNF model' in vnf
:
867 error_text
+= " 'VNF model' " + vnf
['VNF model']
868 WHERE_
['name'] = vnf
['VNF model']
870 return -HTTP_Bad_Request
, "needed a 'vnf_id' or 'VNF model' at " + error_pos
871 r
,vnf_db
= mydb
.get_table(SELECT
=('uuid','name','description'), FROM
='vnfs', WHERE
=WHERE_
)
873 print "nfvo.new_scenario Error getting vnfs",r
,vnf_db
875 print "nfvo.new_scenario Error" + error_text
+ " is not present at database"
876 return -HTTP_Bad_Request
, "unknown" + error_text
+ " at " + error_pos
878 print "nfvo.new_scenario Error more than one" + error_text
+ " are present at database"
879 return -HTTP_Bad_Request
, "more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'"
880 vnf
['uuid']=vnf_db
[0]['uuid']
881 vnf
['description']=vnf_db
[0]['description']
882 #get external interfaces
883 r
,ext_ifaces
= mydb
.get_table(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
884 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
885 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
887 print "nfvo.new_scenario Error getting external interfaces of vnfs",r
,ext_ifaces
888 return -HTTP_Internal_Server_Error
, "Error getting external interfaces of vnfs: " + ext_ifaces
889 for ext_iface
in ext_ifaces
:
890 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
892 #1.4 get list of connections
893 conections
= topo
['topology']['connections']
895 for k
in conections
.keys():
896 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
897 ifaces_list
= conections
[k
]['nodes'].items()
898 elif type(conections
[k
]['nodes'])==list: #list with dictionary
900 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
901 for k2
in conection_pair_list
:
904 con_type
= conections
[k
].get("type", "link")
905 if con_type
!= "link":
907 return -HTTP_Bad_Request
, "format error. Reapeted network name at 'topology':'connections':'%s'" % (str(k
))
908 other_nets
[k
] = {'external': False}
909 if conections
[k
].get("graph"):
910 other_nets
[k
]["graph"] = conections
[k
]["graph"]
911 ifaces_list
.append( (k
, None) )
914 if con_type
== "external_network":
915 other_nets
[k
]['external'] = True
916 if conections
[k
].get("model"):
917 other_nets
[k
]["model"] = conections
[k
]["model"]
919 other_nets
[k
]["model"] = k
920 if con_type
== "dataplane_net" or con_type
== "bridge_net":
921 other_nets
[k
]["model"] = con_type
924 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)
925 #print set(ifaces_list)
926 #check valid VNF and iface names
927 for iface
in ifaces_list
:
928 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
929 return -HTTP_Bad_Request
, "format error. Invalid VNF name at 'topology':'connections':'%s':'nodes':'%s'" % (str(k
), iface
[0])
930 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
931 return -HTTP_Bad_Request
, "format error. Invalid interface name at 'topology':'connections':'%s':'nodes':'%s':'%s'" % (str(k
), iface
[0], iface
[1])
933 #1.5 unify connections from the pair list to a consolidated list
935 while index
< len(conections_list
):
937 while index2
< len(conections_list
):
938 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
939 conections_list
[index
] |
= conections_list
[index2
]
940 del conections_list
[index2
]
943 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
945 #for k in conections_list:
950 #1.6 Delete non external nets
951 # for k in other_nets.keys():
952 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
953 # for con in conections_list:
955 # for index in range(0,len(con)):
956 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
957 # for index in delete_indexes:
960 #1.7: Check external_ports are present at database table datacenter_nets
961 for k
,net
in other_nets
.items():
962 error_pos
= "'topology':'nodes':'" + k
+ "'"
963 if net
['external']==False:
964 if 'name' not in net
:
966 if 'model' not in net
:
967 return -HTTP_Bad_Request
, "needed a 'model' at " + error_pos
968 if net
['model']=='bridge_net':
969 net
['type']='bridge';
970 elif net
['model']=='dataplane_net':
973 return -HTTP_Bad_Request
, "unknown 'model' '"+ net
['model'] +"' at " + error_pos
975 #IF we do not want to check that external network exist at datacenter
980 # if 'net_id' in net:
981 # error_text += " 'net_id' " + net['net_id']
982 # WHERE_['uuid'] = net['net_id']
984 # error_text += " 'model' " + net['model']
985 # WHERE_['name'] = net['model']
986 # if len(WHERE_) == 0:
987 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
988 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
989 # FROM='datacenter_nets', WHERE=WHERE_ )
991 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
993 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
994 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
996 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
997 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
998 # other_nets[k].update(net_db[0])
1001 net_nb
=0 #Number of nets
1002 for con
in conections_list
:
1003 #check if this is connected to a external net
1007 for index
in range(0,len(con
)):
1008 #check if this is connected to a external net
1009 for net_key
in other_nets
.keys():
1010 if con
[index
][0]==net_key
:
1011 if other_net_index
>=0:
1012 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1013 print "nfvo.new_scenario " + error_text
1014 return -HTTP_Bad_Request
, error_text
1016 other_net_index
= index
1017 net_target
= net_key
1019 #print "other_net_index", other_net_index
1021 if other_net_index
>=0:
1022 del con
[other_net_index
]
1023 #IF we do not want to check that external network exist at datacenter
1024 if other_nets
[net_target
]['external'] :
1025 if "name" not in other_nets
[net_target
]:
1026 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1027 if other_nets
[net_target
]["type"] == "external_network":
1028 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1029 other_nets
[net_target
]["type"] = "data"
1031 other_nets
[net_target
]["type"] = "bridge"
1033 # if other_nets[net_target]['external'] :
1034 # 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
1035 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1036 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1037 # print "nfvo.new_scenario " + error_text
1038 # return -HTTP_Bad_Request, error_text
1041 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1044 net_type_bridge
=False
1046 net_target
= "__-__net"+str(net_nb
)
1047 net_list
[net_target
] = {'name': "net-"+str(net_nb
), 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1050 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1051 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1052 if iface_type
=='mgmt' or iface_type
=='bridge':
1053 net_type_bridge
= True
1055 net_type_data
= True
1056 if net_type_bridge
and net_type_data
:
1057 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1058 print "nfvo.new_scenario " + error_text
1059 return -HTTP_Bad_Request
, error_text
1060 elif net_type_bridge
:
1063 type_
='data' if len(con
)>2 else 'ptp'
1064 net_list
[net_target
]['type'] = type_
1067 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1068 print "nfvo.new_scenario " + error_text
1070 return -HTTP_Bad_Request
, error_text
1072 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1073 #1.8.1 obtain management net
1074 r
,mgmt_net
= mydb
.get_table(SELECT
=('uuid','name','description','type','shared'),
1075 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1076 #1.8.2 check all interfaces from all vnfs
1078 add_mgmt_net
= False
1079 for vnf
in vnfs
.values():
1080 for iface
in vnf
['ifaces'].values():
1081 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1082 #iface not connected
1083 iface
['net_key'] = 'mgmt'
1085 if add_mgmt_net
and 'mgmt' not in net_list
:
1086 net_list
['mgmt']=mgmt_net
[0]
1087 net_list
['mgmt']['external']=True
1088 net_list
['mgmt']['graph']={'visible':False}
1090 net_list
.update(other_nets
)
1092 print 'net_list', net_list
1097 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1098 r
,c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1099 'tenant_id':tenant_id
, 'name':topo
['name'],
1100 'description':topo
.get('description',topo
['name']),
1101 'public': topo
.get('public', False)
1106 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
):
1107 scenario
= scenario_dict
["scenario"]
1108 if tenant_id
!= "any":
1109 if not check_tenant(mydb
, tenant_id
):
1110 print 'nfvo.new_scenario_v02() tenant %s not found' % tenant_id
1111 return -HTTP_Not_Found
, 'Tenant %s not found' % tenant_id
1112 if "tenant_id" in scenario
:
1113 if scenario
["tenant_id"] != tenant_id
:
1114 print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1115 return -HTTP_Unauthorized
, "VNF can not have a different tenant owner '%s', must be '%s'" %(scenario
["tenant_id"], tenant_id
)
1119 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1120 for name
,vnf
in scenario
["vnfs"].iteritems():
1123 error_pos
= "'topology':'nodes':'" + name
+ "'"
1125 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1126 WHERE_
['uuid'] = vnf
['vnf_id']
1127 if 'vnf_name' in vnf
:
1128 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1129 WHERE_
['name'] = vnf
['vnf_name']
1130 if len(WHERE_
) == 0:
1131 return -HTTP_Bad_Request
, "needed a 'vnf_id' or 'VNF model' at " + error_pos
1132 r
,vnf_db
= mydb
.get_table(SELECT
=('uuid','name','description'), FROM
='vnfs', WHERE
=WHERE_
)
1134 print "nfvo.new_scenario Error getting vnfs",r
,vnf_db
1136 print "nfvo.new_scenario Error" + error_text
+ " is not present at database"
1137 return -HTTP_Bad_Request
, "unknown" + error_text
+ " at " + error_pos
1139 print "nfvo.new_scenario Error more than one" + error_text
+ " are present at database"
1140 return -HTTP_Bad_Request
, "more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'"
1141 vnf
['uuid']=vnf_db
[0]['uuid']
1142 vnf
['description']=vnf_db
[0]['description']
1144 #get external interfaces
1145 r
,ext_ifaces
= mydb
.get_table(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1146 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1147 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1149 print "nfvo.new_scenario Error getting external interfaces of vnfs",r
,ext_ifaces
1150 return -HTTP_Internal_Server_Error
, "Error getting external interfaces of vnfs: " + ext_ifaces
1151 for ext_iface
in ext_ifaces
:
1152 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1154 #2: Insert net_key at every vnf interface
1155 for net_name
,net
in scenario
["networks"].iteritems():
1156 net_type_bridge
=False
1158 for iface_dict
in net
["interfaces"]:
1159 for vnf
,iface
in iface_dict
.iteritems():
1160 if vnf
not in scenario
["vnfs"]:
1161 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1162 print "nfvo.new_scenario_v02 " + error_text
1163 return -HTTP_Bad_Request
, error_text
1164 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1165 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1166 print "nfvo.new_scenario_v02 " + error_text
1167 return -HTTP_Bad_Request
, error_text
1168 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1169 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1170 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1171 print "nfvo.new_scenario_v02 " + error_text
1172 return -HTTP_Bad_Request
, error_text
1173 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1174 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1175 if iface_type
=='mgmt' or iface_type
=='bridge':
1176 net_type_bridge
= True
1178 net_type_data
= True
1179 if net_type_bridge
and net_type_data
:
1180 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1181 print "nfvo.new_scenario " + error_text
1182 return -HTTP_Bad_Request
, error_text
1183 elif net_type_bridge
:
1186 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1188 net
['name'] = net_name
1189 net
['external'] = net
.get('external', False)
1191 #3: insert at database
1192 scenario
["nets"] = scenario
["networks"]
1193 scenario
['tenant_id'] = tenant_id
1194 r
,c
= mydb
.new_scenario( scenario
)
1198 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1199 data
["uuid"] = scenario_id
1200 data
["tenant_id"] = tenant_id
1201 r
,c
= mydb
.edit_scenario( data
)
1204 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1205 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1206 datacenter_id
= None
1207 datacenter_name
=None
1208 if datacenter
!= None:
1209 if utils
.check_valid_uuid(datacenter
):
1210 datacenter_id
= datacenter
1212 datacenter_name
= datacenter
1213 result
, vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
)
1215 logger
.error("start_scenario error. Datacenter not found")
1218 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
1220 logger
.error("start_scenario error. Several datacenters available, you must concrete")
1221 return -HTTP_Bad_Request
, "Several datacenters available, you must concrete"
1222 myvim
= vims
.values()[0]
1223 myvim_tenant
= myvim
['tenant_id']
1224 datacenter_id
= myvim
['id']
1225 datacenter_name
= myvim
['name']
1226 datacenter_tenant_id
= myvim
['config']['datacenter_tenant_id']
1229 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1230 result
, scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1232 logger
.error("start_scenario error. Error interacting with NFVO DB")
1233 return result
, scenarioDict
1235 logger
.error("start_scenario error. Scenario not found")
1236 return result
, scenarioDict
1238 scenarioDict
['datacenter_tenant_id'] = datacenter_tenant_id
1239 scenarioDict
['datacenter_id'] = datacenter_id
1240 #print '================scenarioDict======================='
1241 #print json.dumps(scenarioDict, indent=4)
1242 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1244 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1245 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1247 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1248 auxNetDict
['scenario'] = {}
1250 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1251 for sce_net
in scenarioDict
['nets']:
1252 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1254 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1255 myNetName
= myNetName
[0:255] #limit length
1256 myNetType
= sce_net
['type']
1258 myNetDict
["name"] = myNetName
1259 myNetDict
["type"] = myNetType
1260 myNetDict
["tenant_id"] = myvim_tenant
1262 #We should use the dictionary as input parameter for new_network
1264 if not sce_net
["external"]:
1265 network_id
= myvim
.new_network(myNetName
, myNetType
)
1266 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1267 sce_net
['vim_id'] = network_id
1268 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1269 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1271 if sce_net
['vim_id'] == None:
1272 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1273 _
, message
= rollback(mydb
, vims
, rollbackList
)
1274 logger
.error("nfvo.start_scenario: %s", error_text
)
1275 return -HTTP_Bad_Request
, error_text
1276 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1277 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1279 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1280 #For each vnf net, we create it and we add it to instanceNetlist.
1281 for sce_vnf
in scenarioDict
['vnfs']:
1282 for net
in sce_vnf
['nets']:
1283 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1285 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1286 myNetName
= myNetName
[0:255] #limit length
1287 myNetType
= net
['type']
1289 myNetDict
["name"] = myNetName
1290 myNetDict
["type"] = myNetType
1291 myNetDict
["tenant_id"] = myvim_tenant
1294 #We should use the dictionary as input parameter for new_network
1295 result
, network_id
= myvim
.new_network(myNetName
, myNetType
)
1296 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1297 net
['vim_id'] = network_id
1298 if sce_vnf
['uuid'] not in auxNetDict
:
1299 auxNetDict
[sce_vnf
['uuid']] = {}
1300 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1301 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1303 #print "auxNetDict:"
1304 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1306 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1307 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1309 for sce_vnf
in scenarioDict
['vnfs']:
1310 for vm
in sce_vnf
['vms']:
1313 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1314 myVMDict
['name'] = "%s.%s.%d" % (instance_scenario_name
,sce_vnf
['name'],i
)
1315 #myVMDict['description'] = vm['description']
1316 myVMDict
['description'] = myVMDict
['name'][0:99]
1318 myVMDict
['start'] = "no"
1319 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1320 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1322 #create image at vim in case it not exist
1323 res
, image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1325 logger
.error("start_scenario error getting image %s", str(image_dict
))
1326 return res
, image_dict
1327 res
, image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1329 logger
.error("start_scenario error adding image to VIM: %s", str(image_dict
))
1330 return res
, image_id
1331 vm
['vim_image_id'] = image_id
1333 #create flavor at vim in case it not exist
1334 res
, flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1336 logger
.error("start_scenario error getting flavor: %s", str(flavor_dict
))
1337 return res
, flavor_dict
1338 if flavor_dict
['extended']!=None:
1339 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1340 res
, flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1342 logger
.error("start_scenario error adding flavor to VIM: ", str(flavor_dict
))
1343 return res
, flavor_id
1344 vm
['vim_flavor_id'] = flavor_id
1347 myVMDict
['imageRef'] = vm
['vim_image_id']
1348 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1349 myVMDict
['networks'] = []
1350 for iface
in vm
['interfaces']:
1352 if iface
['type']=="data":
1353 netDict
['type'] = iface
['model']
1354 elif "model" in iface
and iface
["model"]!=None:
1355 netDict
['model']=iface
['model']
1356 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1357 #discover type of interface looking at flavor
1358 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1359 for flavor_iface
in numa
.get('interfaces',[]):
1360 if flavor_iface
.get('name') == iface
['internal_name']:
1361 if flavor_iface
['dedicated'] == 'yes':
1362 netDict
['type']="PF" #passthrough
1363 elif flavor_iface
['dedicated'] == 'no':
1364 netDict
['type']="VF" #siov
1365 elif flavor_iface
['dedicated'] == 'yes:sriov':
1366 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1367 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1369 netDict
["use"]=iface
['type']
1370 if netDict
["use"]=="data" and not netDict
.get("type"):
1371 #print "netDict", netDict
1372 #print "iface", iface
1373 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'])
1374 if flavor_dict
.get('extended')==None:
1375 return -HTTP_Conflict
, e_text
+ "After database migration some information is not available. \
1376 Try to delete and create the scenarios and VNFs again"
1378 return -HTTP_Internal_Server_Error
, e_text
1379 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1380 netDict
["type"]="virtual"
1381 if "vpci" in iface
and iface
["vpci"] is not None:
1382 netDict
['vpci'] = iface
['vpci']
1383 if "mac" in iface
and iface
["mac"] is not None:
1384 netDict
['mac_address'] = iface
['mac']
1385 netDict
['name'] = iface
['internal_name']
1386 if iface
['net_id'] is None:
1387 for vnf_iface
in sce_vnf
["interfaces"]:
1390 if vnf_iface
['interface_id']==iface
['uuid']:
1391 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1394 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1395 #skip bridge ifaces not connected to any net
1396 #if 'net_id' not in netDict or netDict['net_id']==None:
1398 myVMDict
['networks'].append(netDict
)
1399 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1400 #print myVMDict['name']
1401 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1402 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1403 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1404 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1405 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1406 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1407 vm
['vim_id'] = vm_id
1408 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1409 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1410 for net
in myVMDict
['networks']:
1412 for iface
in vm
['interfaces']:
1413 if net
["name"]==iface
["internal_name"]:
1414 iface
["vim_id"]=net
["vim_id"]
1417 logger
.debug("start scenario Deployment done")
1418 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1419 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1420 result
,c
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1422 error_text
= c
+ "."
1423 _
, message
= rollback(mydb
, vims
, rollbackList
)
1424 error_text
+= message
1425 print "start_scenario: " + error_text
1426 return result
, error_text
1428 return mydb
.get_instance_scenario(c
)
1429 except vimconn
.vimconnException
as e
:
1430 _
, message
= rollback(mydb
, vims
, rollbackList
)
1431 error_text
= "VIM exception {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1432 logger
.error("start_scenario %s", error_text
)
1433 return -e
.http_code
, error_text
1435 def create_instance(mydb
, tenant_id
, instance_dict
):
1436 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1437 scenario
= instance_dict
["scenario"]
1438 datacenter_id
= None
1439 datacenter_name
=None
1440 datacenter
= instance_dict
.get("datacenter")
1442 if utils
.check_valid_uuid(datacenter
):
1443 datacenter_id
= datacenter
1445 datacenter_name
= datacenter
1446 result
, vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
=None)
1448 logger
.error("create_instance error. Datacenter not found")
1451 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
1453 logger
.error("create_instance error. Several datacenters available, you must concrete")
1454 return -HTTP_Bad_Request
, "Several datacenters available, you must concrete"
1455 myvim
= vims
.values()[0]
1456 #myvim_tenant = myvim['tenant_id']
1457 datacenter_id
= myvim
['id']
1458 datacenter_name
= myvim
['name']
1459 datacenter_tenant_id
= myvim
['config']['datacenter_tenant_id']
1462 #print "Checking that the scenario exists and getting the scenario dictionary"
1463 result
, scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_id
)
1465 logger
.error("create_instance error. Error interacting with NFVO DB")
1466 return result
, scenarioDict
1468 logger
.error("create_instance error. Scenario not found")
1469 return result
, scenarioDict
1471 scenarioDict
['datacenter_tenant_id'] = datacenter_tenant_id
1472 scenarioDict
['datacenter_id'] = datacenter_id
1474 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1475 auxNetDict
['scenario'] = {}
1477 #print "scenario dict: ",yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1478 instance_name
= instance_dict
["name"]
1479 instance_description
= instance_dict
.get("description")
1481 #0 check correct parameters
1482 for descriptor_net
in instance_dict
.get("networks",{}).keys():
1484 for scenario_net
in scenarioDict
['nets']:
1485 if descriptor_net
== scenario_net
["name"]:
1489 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(descriptor_net
), HTTP_Bad_Request
)
1490 for descriptor_vnf
in instance_dict
.get("vnfs",{}).keys():
1492 for scenario_vnf
in scenarioDict
['vnfs']:
1493 if descriptor_vnf
== scenario_vnf
['name']:
1497 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(descriptor_vnf
), HTTP_Bad_Request
)
1499 #1. Creating new nets (sce_nets) in the VIM"
1500 for sce_net
in scenarioDict
['nets']:
1501 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
1502 net_name
= descriptor_net
.get("name")
1503 net_type
= sce_net
['type']
1504 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
1505 if sce_net
["external"]:
1507 net_name
= sce_net
["name"]
1508 if "netmap-use" in descriptor_net
or "netmap-create" in descriptor_net
:
1509 create_network
= False
1510 lookfor_network
= False
1511 if "netmap-use" in descriptor_net
:
1512 lookfor_network
= True
1513 if utils
.check_valid_uuid(descriptor_net
["netmap-use"]):
1514 filter_text
= "scenario id '%s'" % descriptor_net
["netmap-use"]
1515 lookfor_filter
["id"] = descriptor_net
["netmap-use"]
1517 filter_text
= "scenario name '%s'" % descriptor_net
["netmap-use"]
1518 lookfor_filter
["name"] = descriptor_net
["netmap-use"]
1519 if "netmap-create" in descriptor_net
:
1520 create_network
= True
1521 net_vim_name
= net_name
1522 if descriptor_net
["netmap-create"]:
1523 net_vim_name
= descriptor_net
["netmap-create"]
1525 elif sce_net
['vim_id'] != None:
1526 #there is a netmap at datacenter_nets database
1527 create_network
= False
1528 lookfor_network
= True
1529 lookfor_filter
["id"] = sce_net
['vim_id']
1530 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
1531 #look for network at datacenter and return error
1533 #There is not a netmap, look at datacenter for a net with this name and create if not found
1534 create_network
= True
1535 lookfor_network
= True
1536 lookfor_filter
["name"] = sce_net
["name"]
1537 net_vim_name
= sce_net
["name"]
1538 filter_text
= "scenario name '%s'" % sce_net
["name"]
1541 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
1542 net_name
= net_name
[:255] #limit length
1543 net_vim_name
= net_name
1544 create_network
= True
1545 lookfor_network
= False
1548 vim_nets
= myvim
.get_network_list(filter_dict
=lookfor_filter
)
1549 if len(vim_nets
) > 1:
1550 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1551 elif len(vim_nets
) == 0:
1552 if not create_network
:
1553 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1555 sce_net
['vim_id'] = vim_nets
[0]['id']
1556 auxNetDict
['scenario'][sce_net
['uuid']] = vim_nets
[0]['id']
1557 create_network
= False
1559 #if network is not external
1560 network_id
= myvim
.new_network(net_vim_name
, net_type
)
1561 sce_net
['vim_id'] = network_id
1562 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1563 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1565 #2. Creating new nets (vnf internal nets) in the VIM"
1566 #For each vnf net, we create it and we add it to instanceNetlist.
1567 for sce_vnf
in scenarioDict
['vnfs']:
1568 for net
in sce_vnf
['nets']:
1569 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
1570 net_name
= descriptor_net
.get("name")
1572 net_name
= "%s.%s" %(instance_name
, net
["name"])
1573 net_name
= net_name
[:255] #limit length
1574 net_type
= net
['type']
1575 network_id
= myvim
.new_network(net_name
, net_type
)
1576 net
['vim_id'] = network_id
1577 if sce_vnf
['uuid'] not in auxNetDict
:
1578 auxNetDict
[sce_vnf
['uuid']] = {}
1579 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1580 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1582 #print "auxNetDict:"
1583 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1585 #3. Creating new vm instances in the VIM
1586 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1587 for sce_vnf
in scenarioDict
['vnfs']:
1589 for vm
in sce_vnf
['vms']:
1592 myVMDict
['name'] = "%s.%s.%d" % (instance_name
,sce_vnf
['name'],i
)
1593 myVMDict
['description'] = myVMDict
['name'][0:99]
1595 # myVMDict['start'] = "no"
1596 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1597 #create image at vim in case it not exist
1598 res
, image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1600 raise NfvoException("Error getting VIM image "+ image_dict
, -result
)
1601 res
, image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1603 raise NfvoException("Error adding image to VIM " + image_dict
, -result
)
1604 vm
['vim_image_id'] = image_id
1606 #create flavor at vim in case it not exist
1607 res
, flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1609 raise NfvoException("Error getting VIM flavor "+ flavor_dict
, -result
)
1610 if flavor_dict
['extended']!=None:
1611 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1612 res
, flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1614 raise NfvoException("Error adding flavor to VIM" + flavor_dict
, -result
)
1615 vm
['vim_flavor_id'] = flavor_id
1617 myVMDict
['imageRef'] = vm
['vim_image_id']
1618 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1619 myVMDict
['networks'] = []
1620 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
1621 for iface
in vm
['interfaces']:
1623 if iface
['type']=="data":
1624 netDict
['type'] = iface
['model']
1625 elif "model" in iface
and iface
["model"]!=None:
1626 netDict
['model']=iface
['model']
1627 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1628 #discover type of interface looking at flavor
1629 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1630 for flavor_iface
in numa
.get('interfaces',[]):
1631 if flavor_iface
.get('name') == iface
['internal_name']:
1632 if flavor_iface
['dedicated'] == 'yes':
1633 netDict
['type']="PF" #passthrough
1634 elif flavor_iface
['dedicated'] == 'no':
1635 netDict
['type']="VF" #siov
1636 elif flavor_iface
['dedicated'] == 'yes:sriov':
1637 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1638 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1640 netDict
["use"]=iface
['type']
1641 if netDict
["use"]=="data" and not netDict
.get("type"):
1642 #print "netDict", netDict
1643 #print "iface", iface
1644 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'])
1645 if flavor_dict
.get('extended')==None:
1646 raise NfvoException(e_text
+ "After database migration some information is not available. \
1647 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1649 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1650 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1651 netDict
["type"]="virtual"
1652 if "vpci" in iface
and iface
["vpci"] is not None:
1653 netDict
['vpci'] = iface
['vpci']
1654 if "mac" in iface
and iface
["mac"] is not None:
1655 netDict
['mac_address'] = iface
['mac']
1656 netDict
['name'] = iface
['internal_name']
1657 if iface
['net_id'] is None:
1658 for vnf_iface
in sce_vnf
["interfaces"]:
1661 if vnf_iface
['interface_id']==iface
['uuid']:
1662 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1665 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1666 #skip bridge ifaces not connected to any net
1667 #if 'net_id' not in netDict or netDict['net_id']==None:
1669 myVMDict
['networks'].append(netDict
)
1670 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1671 #print myVMDict['name']
1672 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1673 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1674 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1675 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1676 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1677 vm
['vim_id'] = vm_id
1678 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1679 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1680 for net
in myVMDict
['networks']:
1682 for iface
in vm
['interfaces']:
1683 if net
["name"]==iface
["internal_name"]:
1684 iface
["vim_id"]=net
["vim_id"]
1686 logger
.debug("create_instance Deployment done")
1687 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1688 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1689 result
,c
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
1691 raise NfvoException(c
, -result
)
1693 return mydb
.get_instance_scenario(c
)
1694 except NfvoException
as e
:
1695 _
, message
= rollback(mydb
, vims
, rollbackList
)
1696 error_text
= "{} {}. {}".format(type(e
).__name
__, str(e
), message
)
1697 logger
.error("create_instance: %s", error_text
)
1698 return -e
.http_code
, error_text
1699 except vimconn
.vimconnException
as e
:
1700 _
, message
= rollback(mydb
, vims
, rollbackList
)
1701 error_text
= "VIM exception {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1702 logger
.error("create_instance: %s", error_text
)
1703 return -e
.http_code
, error_text
1705 def delete_instance(mydb
, tenant_id
, instance_id
):
1706 #print "Checking that the instance_id exists and getting the instance dictionary"
1707 result
, instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
1709 logger
.error("nfvo.delete_instance() error. Error getting info from database")
1710 return result
, instanceDict
1712 logger
.error("delete_instance error. Instance not found")
1713 return result
, instanceDict
1714 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
1715 tenant_id
= instanceDict
["tenant_id"]
1716 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1717 result
, vims
= get_vim(mydb
, tenant_id
, instanceDict
['datacenter_id'])
1719 logger
.error("nfvo.delete_instance() error. Datacenter error %s %s", result
, vims
)
1722 logger
.error("!!!!!! nfvo.delete_instance() datacenter not found!!!!")
1725 myvim
= vims
.values()[0]
1728 #1. Delete from Database
1730 #result,c = mydb.delete_row('instance_scenarios', instance_id, nfvo_tenant)
1731 result
,c
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
1737 error_msg
= "Not possible to delete VIM VMs and networks. Datacenter not found at database!!!"
1743 for sce_vnf
in instanceDict
['vnfs']:
1746 for vm
in sce_vnf
['vms']:
1748 myvim
.delete_vminstance(vm
['vim_vm_id'])
1749 except vimconn
.vimconnNotFoundException
as e
:
1750 error_msg
+="\n VM id={} not found at VIM".format(vm
['vim_vm_id'])
1751 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
1752 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
1753 except vimconn
.vimconnException
as e
:
1754 error_msg
+="\n Error: " + e
.http_code
+ " VM id=" + vm
['vim_vm_id']
1755 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s': %s",
1756 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
1760 for net
in instanceDict
['nets']:
1762 continue #skip not created nets
1766 myvim
.delete_network(net
['vim_net_id'])
1767 except vimconn
.vimconnNotFoundException
as e
:
1768 error_msg
+="\n NET id={} not found at VIM".format(net
['vim_net_id'])
1769 logger
.warn("NET '%s', VIM id '%s', from VNF_id '%s' not found",
1770 net
['uuid'], vm
['vim_net_id'], sce_vnf
['vnf_id'])
1771 except vimconn
.vimconnException
as e
:
1772 error_msg
+="\n Error: " + e
.http_code
+ " Net id=" + net
['vim_vm_id']
1773 logger
.error("Error %d deleting NET '%s', VIM id '%s', from VNF_id '%s': %s",
1774 e
.http_code
, net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'], str(e
))
1775 if len(error_msg
)>0:
1776 return 1, 'instance ' + instance_id
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
1778 return 1, 'instance ' + instance_id
+ ' deleted'
1780 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
1781 '''Refreshes a scenario instance. It modifies instanceDict'''
1783 - 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
1786 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
1787 #print "nfvo.refresh_instance begins"
1788 #print json.dumps(instanceDict, indent=4)
1790 #print "Getting the VIM URL and the VIM tenant_id"
1791 result
, vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
1793 logger
.error("nfvo.refresh_instance() error. Datacenter not found")
1796 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(instanceDict
['datacenter_id'])
1797 myvim
= vims
.values()[0]
1799 # 1. Getting VIM vm and net list
1800 vms_updated
= [] #List of VM instance uuids in openmano that were updated
1803 for sce_vnf
in instanceDict
['vnfs']:
1804 for vm
in sce_vnf
['vms']:
1805 vm_list
.append(vm
['vim_vm_id'])
1806 vms_notupdated
.append(vm
["uuid"])
1808 nets_updated
= [] #List of VM instance uuids in openmano that were updated
1811 for net
in instanceDict
['nets']:
1812 net_list
.append(net
['vim_net_id'])
1813 nets_notupdated
.append(net
["uuid"])
1816 # 1. Getting the status of all VMs
1817 vm_dict
= myvim
.refresh_vms_status(vm_list
)
1819 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
1820 for sce_vnf
in instanceDict
['vnfs']:
1821 for vm
in sce_vnf
['vms']:
1822 vm_id
= vm
['vim_vm_id']
1823 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
1824 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
1825 has_mgmt_iface
= False
1826 for iface
in vm
["interfaces"]:
1827 if iface
["type"]=="mgmt":
1828 has_mgmt_iface
= True
1829 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
1830 vm_dict
[vm_id
]['status'] = "ACTIVE"
1831 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'):
1832 vm
['status'] = vm_dict
[vm_id
]['status']
1833 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
1834 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
1835 # 2.1. Update in openmano DB the VMs whose status changed
1836 result2
, _
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
1838 logger
.error("nfvo.refresh_instance error database update: %s", result2
)
1840 vms_notupdated
.remove(vm
["uuid"])
1842 vms_updated
.append(vm
["uuid"])
1843 # 2.2. Update in openmano DB the interface VMs
1844 for interface
in interfaces
:
1845 #translate from vim_net_id to instance_net_id
1847 for net
in instanceDict
['nets']:
1848 if net
["vim_net_id"] == interface
["vim_net_id"]:
1849 network_id
= net
["uuid"]
1853 del interface
["vim_net_id"]
1854 result2
, _
= mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
1856 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
1858 # 3. Getting the status of all nets
1859 net_dict
= myvim
.refresh_nets_status(net_list
)
1861 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
1862 # TODO: update nets inside a vnf
1863 for net
in instanceDict
['nets']:
1864 net_id
= net
['vim_net_id']
1865 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'):
1866 net
['status'] = net_dict
[net_id
]['status']
1867 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
1868 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
1869 # 5.1. Update in openmano DB the nets whose status changed
1870 result2
, _
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
1872 logger
.error("nfvo.refresh_instance error database update: %s", result2
)
1874 nets_notupdated
.remove(net
["uuid"])
1876 nets_updated
.append(net
["uuid"])
1877 except vimconn
.vimconnException
as e
:
1878 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
1879 return -e
.http_code
, str(e
)
1881 # Returns appropriate output
1882 #print "nfvo.refresh_instance finishes"
1883 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
1884 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
1885 instance_id
= instanceDict
['uuid']
1886 if len(vms_notupdated
)+len(nets_notupdated
)>0:
1887 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
1888 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
1890 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
1892 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
1893 #print "Checking that the instance_id exists and getting the instance dictionary"
1894 result
, instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
1896 logger
.error("nfvo.instance_action() error. Error getting info from database")
1897 return result
, instanceDict
1899 logger
.error("instance_action error. Instance not found")
1900 return -HTTP_Not_Found
, "instance {} not found".format(instance_id
)
1901 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
1903 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1904 result
, vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
1906 logger
.error("nfvo.instance_action() error. Datacenter not found")
1909 return -HTTP_Not_Found
, "datacenter '{}' not found".format(str(instanceDict
['datacenter_id']))
1910 myvim
= vims
.values()[0]
1913 input_vnfs
= action_dict
.pop("vnfs", [])
1914 input_vms
= action_dict
.pop("vms", [])
1915 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
1919 for sce_vnf
in instanceDict
['vnfs']:
1920 for vm
in sce_vnf
['vms']:
1921 if not action_over_all
:
1922 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
1923 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
1926 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
1927 if "console" in action_dict
:
1928 if data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
1929 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
1930 "description": "this console is only reachable by local interface",
1935 #print "console data", data
1936 r2
, console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
1938 vm_result
[ vm
['uuid'] ] = {"vim_result": -r2
, "name":vm
['name'], "description": console_thread
}
1940 vm_result
[ vm
['uuid'] ] = {"vim_result": result
,
1941 "description": "%s//%s:%d/%s" %(data
["protocol"], console_thread
.host
, console_thread
.port
, data
["suffix"]),
1946 vm_result
[ vm
['uuid'] ] = {"vim_result": result
, "description": "ok", "name":vm
['name']}
1948 except vimconn
.vimconnException
as e
:
1949 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
1952 if vm_ok
==0: #all goes wrong
1957 def create_or_use_console_proxy_thread(console_server
, console_port
):
1958 #look for a non-used port
1959 console_thread_key
= console_server
+ ":" + str(console_port
)
1960 if console_thread_key
in global_config
["console_thread"]:
1961 #global_config["console_thread"][console_thread_key].start_timeout()
1962 return 1, global_config
["console_thread"][console_thread_key
]
1964 for port
in global_config
["console_port_iterator"]():
1965 print "create_or_use_console_proxy_thread() port:", port
1966 if port
in global_config
["console_ports"]:
1969 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
1971 global_config
["console_thread"][console_thread_key
] = clithread
1972 global_config
["console_ports"][port
] = console_thread_key
1974 except cli
.ConsoleProxyExceptionPortUsed
as e
:
1975 #port used, try with onoher
1977 except cli
.ConsoleProxyException
as e
:
1979 return -1, "Not found any free 'http_console_ports'"
1981 def check_tenant(mydb
, tenant_id
):
1982 '''check that tenant exists at database'''
1983 result
, _
= mydb
.get_table(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
1984 if result
<=0: return False
1987 def new_tenant(mydb
, tenant_dict
):
1988 result
, tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, None, add_uuid
=True, log
=True)
1990 return result
, tenant_id
1991 return 200,tenant_id
1993 def delete_tenant(mydb
, tenant
):
1994 #get nfvo_tenant info
1995 result
,tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
1997 return result
, tenant_dict
1999 result
, tenant_id
= mydb
.delete_row("nfvo_tenants", tenant_dict
['uuid'], None)
2001 return result
, tenant_id
2002 return 200, tenant_dict
['uuid']
2004 def new_datacenter(mydb
, datacenter_descriptor
):
2005 if "config" in datacenter_descriptor
:
2006 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2007 result
, datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, None, add_uuid
=True, log
=True)
2009 return result
, datacenter_id
2010 return 200,datacenter_id
2012 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2013 #obtain data, check that only one exist
2014 result
, content
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2016 return result
, content
2018 datacenter_id
= content
['uuid']
2019 where
={'uuid': content
['uuid']}
2020 if "config" in datacenter_descriptor
:
2021 if datacenter_descriptor
['config']!=None:
2023 new_config_dict
= datacenter_descriptor
["config"]
2026 for k
in new_config_dict
:
2027 if new_config_dict
[k
]==None:
2030 config_dict
= yaml
.load(content
["config"])
2031 config_dict
.update(new_config_dict
)
2036 return -HTTP_Bad_Request
, "Bad format at datacenter:config " + str(e
)
2037 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2038 result
, content
= mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2040 return result
, datacenter_id
2041 return 200, datacenter_id
2043 def delete_datacenter(mydb
, datacenter
):
2044 #get nfvo_tenant info
2045 result
,datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2047 return result
, datacenter_dict
2049 result
, datacenter_id
= mydb
.delete_row("datacenters", datacenter_dict
['uuid'], None)
2051 return result
, datacenter_id
2052 return 200, datacenter_dict
['uuid']
2054 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None):
2055 #get datacenter info
2056 if utils
.check_valid_uuid(datacenter
):
2057 result
, vims
= get_vim(mydb
, datacenter_id
=datacenter
)
2059 result
, vims
= get_vim(mydb
, datacenter_name
=datacenter
)
2061 print "nfvo.associate_datacenter_to_tenant() error. Datacenter not found"
2064 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2066 print "nfvo.associate_datacenter_to_tenant() error. Several datacenters found"
2068 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2069 datacenter_id
=vims
.keys()[0]
2070 myvim
=vims
[datacenter_id
]
2071 datacenter_name
=myvim
["name"]
2073 create_vim_tenant
=True if vim_tenant_id
==None and vim_tenant_name
==None else False
2075 #get nfvo_tenant info
2076 result
,tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2078 return result
, tenant_dict
2079 if vim_tenant_name
==None:
2080 vim_tenant_name
=tenant_dict
['name']
2082 #check that this association does not exist before
2083 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2084 result
,content
= mydb
.get_table(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2086 return -HTTP_Conflict
, "datacenter %s and tenant %s are already attached" %(datacenter_id
, tenant_dict
['uuid'])
2088 return result
, content
2090 vim_tenant_id_exist_atdb
=False
2091 if not create_vim_tenant
:
2092 where_
={"datacenter_id": datacenter_id
}
2093 if vim_tenant_id
!=None:
2094 where_
["vim_tenant_id"] = vim_tenant_id
2095 if vim_tenant_name
!=None:
2096 where_
["vim_tenant_name"] = vim_tenant_name
2097 #check if vim_tenant_id is already at database
2098 result
,datacenter_tenants_dict
= mydb
.get_table(FROM
='datacenter_tenants', WHERE
=where_
)
2100 return result
, datacenter_tenants_dict
2102 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2103 vim_tenant_id_exist_atdb
=True
2104 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2106 datacenter_tenants_dict
= {}
2107 #insert at table datacenter_tenants
2108 else: #if vim_tenant_id==None:
2109 #create tenant at VIM if not provided
2111 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2112 except vimconn
.vimconnException
as e
:
2113 return -HTTP_Internal_Server_Error
, "Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
))
2114 datacenter_tenants_dict
= {}
2115 datacenter_tenants_dict
["created"]="true"
2117 #fill datacenter_tenants table
2118 if not vim_tenant_id_exist_atdb
:
2119 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2120 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2121 datacenter_tenants_dict
["user"] = vim_username
2122 datacenter_tenants_dict
["passwd"] = vim_password
2123 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2124 res
,id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, tenant_dict
['uuid'], True, True)
2126 return -HTTP_Bad_Request
, "Not possible to add %s to database datacenter_tenants table %s " %(vim_tenant_id
, id_
)
2127 datacenter_tenants_dict
["uuid"] = id_
2129 #fill tenants_datacenters table
2130 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2131 res
,id_
= mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
, tenant_dict
['uuid'], False, True)
2133 return -HTTP_Bad_Request
, "Not possible to create an entry at database table datacenter_tenants: " + id_
2134 return 200, datacenter_id
2136 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2137 #get datacenter info
2138 if utils
.check_valid_uuid(datacenter
):
2139 result
, vims
= get_vim(mydb
, datacenter_id
=datacenter
)
2141 result
, vims
= get_vim(mydb
, datacenter_name
=datacenter
)
2143 print "nfvo.deassociate_datacenter_to_tenant() error. Datacenter not found"
2146 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2148 print "nfvo.deassociate_datacenter_to_tenant() error. Several datacenters found"
2149 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2150 datacenter_id
=vims
.keys()[0]
2151 myvim
=vims
[datacenter_id
]
2153 #get nfvo_tenant info
2154 if not tenant_id
or tenant_id
=="any":
2157 result
,tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2159 return result
, tenant_dict
2160 tenant_uuid
= tenant_dict
['uuid']
2162 #check that this association exist before
2163 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2165 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2166 result
,tenant_datacenter_list
= mydb
.get_table(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2167 if result
==0 and tenant_uuid
:
2168 return -HTTP_Not_Found
, "datacenter %s and tenant %s are not attached" %(datacenter_id
, tenant_dict
['uuid'])
2170 return result
, tenant_datacenter_list
2172 #delete this association
2173 result
,data
= mydb
.delete_row_by_dict(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2177 #get vim_tenant info and deletes
2179 for tenant_datacenter_item
in tenant_datacenter_list
:
2180 result
,vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2182 #try to delete vim:tenant
2183 result
,data
= mydb
.delete_row('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'], tenant_uuid
)
2185 pass #the error will be caused because dependencies, vim_tenant can not be deleted
2186 elif vim_tenant_dict
['created']=='true':
2187 #delete tenant at VIM if created by NFVO
2189 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2190 except vimconn
.vimconnException
as e
:
2191 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2192 logger
.warn(warning
)
2194 return 200, "datacenter %s detached.%s" %(datacenter_id
, warning
)
2196 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2198 #get datacenter info
2199 if utils
.check_valid_uuid(datacenter
):
2200 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2202 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2204 logger
.error("nfvo.datacenter_action() error. Datacenter not found")
2207 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2209 logger
.error("nfvo.datacenter_action() error. Several datacenters found")
2210 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2211 datacenter_id
=vims
.keys()[0]
2212 myvim
=vims
[datacenter_id
]
2214 if 'net-update' in action_dict
:
2216 content
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2218 except vimconn
.vimconnException
as e
:
2219 logger
.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e
))
2220 return -HTTP_Internal_Server_Error
, str(e
)
2221 #update nets Change from VIM format to NFVO format
2224 net_nfvo
={'datacenter_id': datacenter_id
}
2225 net_nfvo
['name'] = net
['name']
2226 #net_nfvo['description']= net['name']
2227 net_nfvo
['vim_net_id'] = net
['id']
2228 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2229 net_nfvo
['shared'] = net
['shared']
2230 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2231 net_list
.append(net_nfvo
)
2232 result
, content
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2234 return -HTTP_Internal_Server_Error
, content
2235 logger
.info("Inserted %d nets, deleted %d old nets", result
, content
)
2238 elif 'net-edit' in action_dict
:
2239 net
= action_dict
['net-edit'].pop('net')
2240 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2241 result
, content
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2242 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2243 return result
, content
2244 elif 'net-delete' in action_dict
:
2245 net
= action_dict
['net-deelte'].get('net')
2246 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2247 result
, content
= mydb
.delete_row_by_dict(FROM
='datacenter_nets',
2248 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2249 return result
, content
2252 return -HTTP_Bad_Request
, "Unknown action " + str(action_dict
)
2254 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2255 #get datacenter info
2256 if utils
.check_valid_uuid(datacenter
):
2257 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2259 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2261 print "nfvo.datacenter_action() error. Datacenter not found"
2264 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2266 print "nfvo.datacenter_action() error. Several datacenters found"
2267 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2268 datacenter_id
=vims
.keys()[0]
2270 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2271 result
, content
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2272 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2273 return result
, content
2275 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2276 #get datacenter info
2277 if utils
.check_valid_uuid(datacenter
):
2278 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2280 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2282 logger
.error("nfvo.datacenter_new_netmap() error. Datacenter not found")
2285 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2287 logger
.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2288 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2289 datacenter_id
=vims
.keys()[0]
2290 myvim
=vims
[datacenter_id
]
2293 action_dict
= action_dict
["netmap"]
2294 if 'vim_id' in action_dict
:
2295 filter_dict
["id"] = action_dict
['vim_id']
2296 if 'vim_name' in action_dict
:
2297 filter_dict
["name"] = action_dict
['vim_name']
2299 filter_dict
["shared"] = True
2302 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2303 except vimconn
.vimconnException
as e
:
2304 logger
.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e
))
2305 return -HTTP_Internal_Server_Error
, str(e
)
2306 if len(content
)>1 and action_dict
:
2307 return -HTTP_Conflict
, "more than two networks found, specify with vim_id"
2308 elif len(content
)==0: # and action_dict:
2309 return -HTTP_Not_Found
, "Not found a network at VIM with " + str(filter_dict
)
2312 net_nfvo
={'datacenter_id': datacenter_id
}
2313 if action_dict
and "name" in action_dict
:
2314 net_nfvo
['name'] = action_dict
['name']
2316 net_nfvo
['name'] = net
['name']
2317 #net_nfvo['description']= net['name']
2318 net_nfvo
['vim_net_id'] = net
['id']
2319 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2320 net_nfvo
['shared'] = net
['shared']
2321 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2322 result
, content
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2323 if action_dict
and result
< 0 :
2324 return result
, content
2326 net_nfvo
["status"] = "FAIL: " + content
2328 net_nfvo
["status"] = "OK"
2329 net_nfvo
["uuid"] = content
2330 net_list
.append(net_nfvo
)
2331 return 200, net_list
2333 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2334 #get datacenter info
2335 if utils
.check_valid_uuid(datacenter
):
2336 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2338 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2340 print "nfvo.datacenter_action() error. Datacenter not found"
2343 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2345 print "nfvo.datacenter_action() error. Several datacenters found"
2346 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2347 datacenter_id
=vims
.keys()[0]
2348 myvim
=vims
[datacenter_id
]
2351 if utils
.check_valid_uuid(name
):
2352 filter_dict
["id"] = name
2354 filter_dict
["name"] = name
2356 if item
=="networks":
2357 #filter_dict['tenant_id'] = myvim['tenant_id']
2358 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2359 elif item
=="tenants":
2360 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2362 return -HTTP_Method_Not_Allowed
, item
+ "?"
2363 print "vim_action response ", content
#update nets Change from VIM format to NFVO format
2364 if name
and len(content
)==1:
2365 return 200, {item
[:-1]: content
[0]}
2366 elif name
and len(content
)==0:
2367 return -HTTP_Not_Found
, "No %s found with %s" % (item
[:-1], " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())))
2369 return 200, {item
: content
}
2370 except vimconn
.vimconnException
as e
:
2371 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
2372 return -e
.http_code
, "Not possible to get_{}_list from VIM: {}".format(item
, str(e
))
2374 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
2375 #get datacenter info
2376 if tenant_id
== "any":
2379 if utils
.check_valid_uuid(datacenter
):
2380 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2382 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2384 print "nfvo.datacenter_action() error. Datacenter not found"
2387 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2389 print "nfvo.datacenter_action() error. Several datacenters found"
2390 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2391 datacenter_id
=vims
.keys()[0]
2392 myvim
=vims
[datacenter_id
]
2394 result
, content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2397 return result
, content
2398 items
= content
.values()[0]
2399 if type(items
)==list and len(items
)==0:
2400 return -HTTP_Not_Found
, "Not found " + item
2401 elif type(items
)==list and len(items
)>1:
2402 return -HTTP_Not_Found
, "Found more than one %s with this name. Use uuid." % item
2403 else: # it is a dict
2404 item_id
= items
["id"]
2405 item_name
= str(items
.get("name"))
2408 if item
=="networks":
2409 content
= myvim
.delete_network(item_id
)
2410 elif item
=="tenants":
2411 content
= myvim
.delete_tenant(item_id
)
2413 return -HTTP_Method_Not_Allowed
, item
+ "?"
2414 except vimconn
.vimconnException
as e
:
2415 print "vim_action Not possible to delete_{} {}from VIM: {} ".format(item
, name
, str(e
))
2416 return -e
.http_code
, "Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
))
2419 print "vim_action Not possible to delete %s %s from VIM: %s " % (item
, name
, content
)
2420 return result
, content
2421 return 200, "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
2423 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2424 #get datacenter info
2425 print "vim_action_create descriptor", descriptor
2426 if tenant_id
== "any":
2429 if utils
.check_valid_uuid(datacenter
):
2430 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2432 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2434 print "nfvo.datacenter_action() error. Datacenter not found"
2437 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2439 print "nfvo.datacenter_action() error. Several datacenters found"
2440 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2441 datacenter_id
=vims
.keys()[0]
2442 myvim
=vims
[datacenter_id
]
2445 if item
=="networks":
2446 net
= descriptor
["network"]
2447 net_name
= net
.pop("name")
2448 net_type
= net
.pop("type", "bridge")
2449 net_public
=net
.pop("shared", False)
2450 content
= myvim
.new_network(net_name
, net_type
, net_public
, **net
)
2451 elif item
=="tenants":
2452 tenant
= descriptor
["tenant"]
2453 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2455 return -HTTP_Method_Not_Allowed
, item
+ "?"
2456 except vimconn
.vimconnException
as e
:
2457 print "vim_action Not possible to create {} at VIM: {} ".format(item
, str(e
))
2458 return -e
.http_code
, "Not possible to create {} at VIM: {}".format(item
, str(e
))
2460 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)