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
39 global vimconn_imported
41 vimconn_imported
={} #dictionary with VIM type as key, loaded module as value
43 class NfvoException(Exception):
44 def __init__(self
, error_code
, text_message
):
45 self
.error_code
= error_code
46 Exception.__init
__(self
, text_message
)
49 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
51 return result, content:
52 <0, error_text upon error
53 nb_records, flavor_list on success
56 WHERE_dict
['vnf_id'] = vnf_id
57 if nfvo_tenant
is not None:
58 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
60 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
61 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
62 result
, content
= mydb
.get_table(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
64 print "nfvo.get_flavorlist error %d %s" % (result
, content
)
65 return -result
, content
66 print "get_flavor_list result:", result
67 print "get_flavor_list content:", content
69 for flavor
in content
:
70 flavorList
.append(flavor
['flavor_id'])
71 return result
, flavorList
73 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
75 return result, content:
76 <0, error_text upon error
77 nb_records, flavor_list on success
80 WHERE_dict
['vnf_id'] = vnf_id
81 if nfvo_tenant
is not None:
82 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
84 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
85 result
, content
= mydb
.get_table(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
87 print "nfvo.get_imagelist error %d %s" % (result
, content
)
88 return -result
, content
89 print "get_image_list result:", result
90 print "get_image_list content:", content
93 imageList
.append(image
['image_id'])
94 return result
, imageList
96 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, vim_tenant
=None):
97 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
98 return result, content:
99 <0, error_text upon error
100 NUMBER, dictionary with datacenter_id: vim_class with these keys:
101 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
104 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
105 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
106 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
107 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
108 if nfvo_tenant
or vim_tenant
:
109 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'
110 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
111 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
114 from_
= 'datacenters as d'
115 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
116 result
, content
= mydb
.get_table(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
118 print "nfvo.get_vim error %d %s" % (result
, content
)
119 return result
, content
121 # print "nfvo.get_vim not found a valid VIM with the input params " + str(WHERE_dict)
122 # return -HTTP_Not_Found, "datacenter not found for " + str(WHERE_dict)
126 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
127 if vim
["config"] != None:
128 extra
.update(yaml
.load(vim
["config"]))
129 if vim
["type"] not in vimconn_imported
:
132 module
= "vimconn_" + vim
["type"]
133 module_info
= imp
.find_module(module
)
134 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
135 vimconn_imported
[vim
["type"]] = vim_conn
136 except (IOError, ImportError) as e
:
137 if module_info
and module_info
[0]:
138 file.close(module_info
[0])
139 print "Cannot open VIM module '%s.py'; %s: %s" % ( module
, type(e
).__name
__, str(e
))
140 return -HTTP_Bad_Request
, "Unknown vim type %s" % vim
["type"]
144 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
145 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
146 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
147 tenant_id
=vim
.get('vim_tenant_id'), tenant_name
=vim
.get('vim_tenant_name'),
148 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
149 user
=vim
.get('user'), passwd
=vim
.get('passwd'),
152 except Exception as e
:
153 return -HTTP_Internal_Server_Error
, "Error at VIM %s; %s: %s" % ( vim
["type"], type(e
).__name
__, str(e
))
154 return len(vim_dict
), vim_dict
156 def rollback(mydb
, vims
, rollback_list
):
158 #delete things by reverse order
159 for i
in range(len(rollback_list
)-1, -1, -1):
160 item
= rollback_list
[i
]
161 if item
["where"]=="vim":
162 if item
["vim_id"] not in vims
:
164 vim
=vims
[ item
["vim_id"] ]
165 if item
["what"]=="image":
166 result
, message
= vim
.delete_tenant_image(item
["uuid"])
168 print "Error in rollback. Not possible to delete VIM image '%s'. Message: %s" % (item
["uuid"],message
)
169 undeleted_items
.append("image %s from VIM %s" % (item
["uuid"],vim
["name"]))
171 result
, message
= mydb
.delete_row_by_dict(FROM
="datacenters_images", WEHRE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
173 print "Error in rollback. Not possible to delete image '%s' from DB.dacenters_images. Message: %s" % (item
["uuid"],message
)
174 elif item
["what"]=="flavor":
175 result
, message
= vim
.delete_tenant_flavor(item
["uuid"])
177 print "Error in rollback. Not possible to delete VIM flavor '%s'. Message: %s" % (item
["uuid"],message
)
178 undeleted_items
.append("flavor %s from VIM %s" % (item
["uuid"],vim
["name"]))
180 result
, message
= mydb
.delete_row_by_dict(FROM
="datacenters_flavos", WEHRE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
182 print "Error in rollback. Not possible to delete flavor '%s' from DB.dacenters_flavors. Message: %s" % (item
["uuid"],message
)
183 elif item
["what"]=="network":
184 result
, message
= vim
.delete_tenant_network(item
["uuid"])
186 print "Error in rollback. Not possible to delete VIM network '%s'. Message: %s" % (item
["uuid"],message
)
187 undeleted_items
.append("network %s from VIM %s" % (item
["uuid"],vim
["name"]))
188 elif item
["what"]=="vm":
189 result
, message
= vim
.delete_tenant_vminstance(item
["uuid"])
191 print "Error in rollback. Not possible to delete VIM VM '%s'. Message: %s" % (item
["uuid"],message
)
192 undeleted_items
.append("VM %s from VIM %s" % (item
["uuid"],vim
["name"]))
194 if item
["what"]=="image":
195 result
, message
= mydb
.delete_row_by_dict(FROM
="images", WEHRE
={"uuid": item
["uuid"]})
197 print "Error in rollback. Not possible to delete image '%s' from DB.images. Message: %s" % (item
["uuid"],message
)
198 undeleted_items
.append("image %s" % (item
["uuid"]))
199 elif item
["what"]=="flavor":
200 result
, message
= mydb
.delete_row_by_dict(FROM
="flavors", WEHRE
={"uuid": item
["uuid"]})
202 print "Error in rollback. Not possible to delete flavor '%s' from DB.flavors. Message: %s" % (item
["uuid"],message
)
203 undeleted_items
.append("flavor %s" % (item
["uuid"]))
204 if len(undeleted_items
)==0:
205 return True," Rollback successful."
207 return False," Rollback fails to delete: " + str(undeleted_items
)
209 def check_vnf_descriptor(vnf_descriptor
):
211 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
213 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
215 #dataplane interfaces
216 for numa
in vnfc
.get("numas",() ):
217 for interface
in numa
.get("interfaces",()):
218 if interface
["name"] in name_list
:
219 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"])
220 name_list
.append( interface
["name"] )
222 for interface
in vnfc
.get("bridge-ifaces",() ):
223 if interface
["name"] in name_list
:
224 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"])
225 name_list
.append( interface
["name"] )
226 vnfc_interfaces
[ vnfc
["name"] ] = name_list
228 #check if the info in external_connections matches with the one in the vnfcs
230 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
231 if external_connection
["name"] in name_list
:
232 return -HTTP_Bad_Request
, "Error at vnf:external-connections:name, value '%s' already used as an external-connection" %(external_connection
["name"])
233 name_list
.append(external_connection
["name"])
234 if external_connection
["VNFC"] not in vnfc_interfaces
:
235 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"])
236 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
237 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"])
239 #check if the info in internal_connections matches with the one in the vnfcs
241 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
242 if internal_connection
["name"] in name_list
:
243 return -HTTP_Bad_Request
, "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection" %(internal_connection
["name"])
244 name_list
.append(internal_connection
["name"])
245 #We should check that internal-connections of type "ptp" have only 2 elements
246 if len(internal_connection
["elements"])>2 and internal_connection
["type"] == "ptp":
247 return -HTTP_Bad_Request
, "Error at vnf:internal-connections[name:'%s']:elements, size must be 2 for a type:'ptp'" %(internal_connection
["name"])
248 for port
in internal_connection
["elements"]:
249 if port
["VNFC"] not in vnfc_interfaces
:
250 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"])
251 if port
["local_iface_name"] not in vnfc_interfaces
[ port
["VNFC"] ]:
252 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"])
257 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
259 if only_create_at_vim
:
260 image_mano_id
= image_dict
['uuid']
262 res
,content
= mydb
.get_table(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
264 image_mano_id
= content
[0]['uuid']
269 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
270 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None)
272 res
,content
= mydb
.new_row('images', temp_image_dict
, tenant_id
=None, add_uuid
=True)
274 image_mano_id
= content
275 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
277 return res
if res
<0 else -1, content
278 #create image at every vim
279 for vim_id
,vim
in vims
.iteritems():
280 image_created
="false"
282 res_db
,image_db
= mydb
.get_table(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
284 return res_db
, image_db
285 #look at VIM if this image exist
286 res_vim
, image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
288 print "Error contacting VIM to know if the image %s existed previously." %image
_vim
_id
291 #Create the image in VIM
292 result
, image_vim_id
= vim
.new_tenant_image(image_dict
)
294 print "Error creating image at VIM: %s." %image
_vim
_id
296 return result
, image_vim_id
299 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
302 #if reach here the image has been create or exist
304 #add new vim_id at datacenters_images
305 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
306 elif image_db
[0]["vim_id"]!=image_vim_id
:
307 #modify existing vim_id at datacenters_images
308 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
310 return 1, image_vim_id
if only_create_at_vim
else image_mano_id
312 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
313 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
314 'ram':flavor_dict
.get('ram'),
315 'vcpus':flavor_dict
.get('vcpus'),
317 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
318 del flavor_dict
['extended']
319 if 'extended' in flavor_dict
:
320 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
322 #look if flavor exist
323 if only_create_at_vim
:
324 flavor_mano_id
= flavor_dict
['uuid']
326 res
,content
= mydb
.get_table(FROM
="flavors", WHERE
=temp_flavor_dict
)
328 flavor_mano_id
= content
[0]['uuid']
333 #create one by one the images of aditional disks
334 dev_image_list
=[] #list of images
335 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
337 for device
in flavor_dict
['extended'].get('devices',[]):
338 if "image" not in device
:
340 image_dict
={'location':device
['image'], 'name':flavor_dict
['name']+str(dev_nb
)+"-img", 'description':flavor_dict
.get('description')}
341 image_metadata_dict
= device
.get('image metadata', None)
342 image_metadata_str
= None
343 if image_metadata_dict
!= None:
344 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
345 image_dict
['metadata']=image_metadata_str
346 res
, image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
348 return res
, image_id
+ rollback(mydb
, vims
, rollback_list
)[1]
349 print "Additional disk image id for VNFC %s: %s" % (flavor_dict
['name']+str(dev_nb
)+"-img", image_id
)
350 dev_image_list
.append(image_id
)
352 temp_flavor_dict
['name'] = flavor_dict
['name']
353 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
354 res
,content
= mydb
.new_row('flavors', temp_flavor_dict
, tenant_id
=None, add_uuid
=True)
356 flavor_mano_id
= content
357 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
359 return res
if res
<0 else -1, content
360 #create flavor at every vim
361 if 'uuid' in flavor_dict
:
362 del flavor_dict
['uuid']
364 for vim_id
,vim
in vims
.items():
365 flavor_created
="false"
367 res_db
,flavor_db
= mydb
.get_table(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
369 return res_db
, flavor_db
370 #look at VIM if this flavor exist SKIPPED
371 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
373 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
377 #Create the flavor in VIM
378 #Translate images at devices from MANO id to VIM id
380 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
381 #make a copy of original devices
383 for device
in flavor_dict
["extended"].get("devices",[]):
386 devices_original
.append(dev
)
387 if 'image' in device
:
389 if 'image metadata' in device
:
390 del device
['image metadata']
392 for index
in range(0,len(devices_original
)) :
393 device
=devices_original
[index
]
394 if "image" not in device
:
396 image_dict
={'location':device
['image'], 'name':flavor_dict
['name']+str(dev_nb
)+"-img", 'description':flavor_dict
.get('description')}
397 image_metadata_dict
= device
.get('image metadata', None)
398 image_metadata_str
= None
399 if image_metadata_dict
!= None:
400 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
401 image_dict
['metadata']=image_metadata_str
402 r
,image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False)
404 print "Error creating device image for flavor: %s." %image
_mano
_id
405 error_text
= image_mano_id
408 image_dict
["uuid"]=image_mano_id
409 r
,image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True)
411 print "Error creating device image for flavor at VIM: %s." %image
_vim
_id
412 error_text
= image_vim_id
415 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
422 #check that this vim_id exist in VIM, if not create
423 flavor_vim_id
=flavor_db
[0]["vim_id"]
424 result
, _
= vim
.get_tenant_flavor(flavor_vim_id
)
425 if result
>=0: #flavor exist
427 #create flavor at vim
428 print "nfvo.create_or_use_flavor() adding flavor to VIM %s" % vim
["name"]
429 result
, flavor_vim_id
= vim
.new_tenant_flavor(flavor_dict
)
432 print "Error creating flavor at VIM %s: %s." %(vim
["name"], flavor_vim_id
)
434 return result
, flavor_vim_id
437 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
438 flavor_created
="true"
440 #if reach here the flavor has been create or exist
442 #add new vim_id at datacenters_flavors
443 mydb
.new_row('datacenters_flavors', {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
, 'created':flavor_created
})
444 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
445 #modify existing vim_id at datacenters_flavors
446 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
448 return 1, flavor_vim_id
if only_create_at_vim
else flavor_mano_id
450 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
453 # Step 1. Check the VNF descriptor
454 result
, message
= check_vnf_descriptor(vnf_descriptor
)
456 print "new_vnf error: %s" %message
457 return result
, message
459 # Step 2. Check tenant exist
460 if tenant_id
!= "any":
461 if not check_tenant(mydb
, tenant_id
):
462 print 'nfvo.new_vnf() tenant %s not found' % tenant_id
463 return -HTTP_Not_Found
, 'Tenant %s not found' % tenant_id
464 if "tenant_id" in vnf_descriptor
["vnf"]:
465 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
466 print "nfvo.new_vnf() tenant '%s' not found" % tenant_id
467 return -HTTP_Unauthorized
, "VNF can not have a different tenant owner '%s', must be '%s'" %(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
)
469 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
470 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
471 result
, vims
= get_vim(mydb
, tenant_id
)
473 print "nfvo.new_vnf() error. Datacenter not found"
478 # Step 4. Review the descriptor and add missing fields
479 #print vnf_descriptor
480 print "Refactoring VNF descriptor with fields: description, public (default: true)"
481 vnf_name
= vnf_descriptor
['vnf']['name']
482 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
483 if "physical" in vnf_descriptor
['vnf']:
484 del vnf_descriptor
['vnf']['physical']
485 #print vnf_descriptor
486 # Step 5. Check internal connections
487 # TODO: to be moved to step 1????
488 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
489 for ic
in internal_connections
:
490 if len(ic
['elements'])>2 and ic
['type']=='ptp':
491 return -HTTP_Bad_Request
, "Mismatch 'type':'ptp' with %d elements at 'vnf':'internal-conections'['name':'%s']. Change 'type' to 'data'" %(len(ic
), ic
['name'])
492 elif len(ic
['elements'])==2 and ic
['type']=='data':
493 return -HTTP_Bad_Request
, "Mismatch 'type':'data' with 2 elements at 'vnf':'internal-conections'['name':'%s']. Change 'type' to 'ptp'" %(ic
['name'])
495 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
496 print 'BEGIN creation of VNF "%s"' % vnf_name
497 print "VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC']))
499 #For each VNFC, we add it to the VNFCDict and we create a flavor.
500 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
501 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
504 print "Creating additional disk images and new flavors in the VIM for each VNFC"
505 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
507 VNFCitem
["name"] = vnfc
['name']
508 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
510 print "Flavor name: %s. Description: %s" % (VNFCitem
["name"]+"-flv", VNFCitem
["description"])
513 myflavorDict
["name"] = vnfc
['name']+"-flv"
514 myflavorDict
["description"] = VNFCitem
["description"]
515 myflavorDict
["ram"] = vnfc
.get("ram", 0)
516 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
517 myflavorDict
["disk"] = vnfc
.get("disk", 1)
518 myflavorDict
["extended"] = {}
520 devices
= vnfc
.get("devices")
522 myflavorDict
["extended"]["devices"] = devices
525 # 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
526 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
528 # Previous code has been commented
529 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
530 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
531 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
532 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
534 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
536 # print "Error creating flavor: unknown processor model. Rollback successful."
537 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
539 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
540 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
542 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
543 myflavorDict
['extended']['numas'] = vnfc
['numas']
547 # Step 6.2 New flavors are created in the VIM
548 res
, flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
550 return res
, flavor_id
+ rollback(mydb
, vims
, rollback_list
)[1]
552 print "Flavor id for VNFC %s: %s" % (vnfc
['name'],flavor_id
)
553 VNFCitem
["flavor_id"] = flavor_id
554 VNFCDict
[vnfc
['name']] = VNFCitem
556 print "Creating new images in the VIM for each VNFC"
557 # Step 6.3 New images are created in the VIM
558 #For each VNFC, we must create the appropriate image.
559 #This "for" loop might be integrated with the previous one
560 #In case this integration is made, the VNFCDict might become a VNFClist.
561 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
562 print "Image name: %s. Description: %s" % (vnfc
['name']+"-img", VNFCDict
[vnfc
['name']]['description'])
563 image_dict
={'location':vnfc
['VNFC image'], 'name':vnfc
['name']+"-img", 'description':VNFCDict
[vnfc
['name']]['description']}
564 image_metadata_dict
= vnfc
.get('image metadata', None)
565 image_metadata_str
= None
566 if image_metadata_dict
is not None:
567 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
568 image_dict
['metadata']=image_metadata_str
569 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
570 res
, image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
572 return res
, image_id
+ rollback(mydb
, vims
, rollback_list
)[1]
573 print "Image id for VNFC %s: %s" % (vnfc
['name'],image_id
)
574 VNFCDict
[vnfc
['name']]["image_id"] = image_id
575 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
['VNFC image']
577 except KeyError as e
:
578 print "Error while creating a VNF. KeyError: " + str(e
)
579 _
, message
= rollback(mydb
, vims
, rollback_list
)
580 return -HTTP_Internal_Server_Error
, "Error while creating a VNF. KeyError " + str(e
) + "." + message
582 # Step 7. Storing the VNF descriptor in the repository
583 if "descriptor" not in vnf_descriptor
["vnf"]:
584 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
586 # Step 8. Adding the VNF to the NFVO DB
588 result
, vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
589 except KeyError as e
:
590 print "Error while creating a VNF. KeyError: " + str(e
)
591 _
, message
= rollback(mydb
, vims
, rollback_list
)
592 return -HTTP_Internal_Server_Error
, "Error while creating a VNF. KeyError " + str(e
) + "." + message
595 _
, message
= rollback(mydb
, vims
, rollback_list
)
596 return result
, vnf_id
+ "." + message
600 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
601 #check valid tenant_id
602 if tenant_id
!= "any" and not check_tenant(mydb
, tenant_id
):
603 print 'nfvo.get_vnf_id() tenant %s not found' % tenant_id
604 return -HTTP_Not_Found
, "Tenant '%s' not found" % tenant_id
607 if tenant_id
!= "any":
608 where_or
["tenant_id"] = tenant_id
609 where_or
["public"] = True
610 result
, content
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
612 print "nfvo.get_vnf_id() error %d %s" % (result
, content
)
613 return (result
, content
)
616 vnf_id
=content
["uuid"]
617 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
618 filtered_content
= dict( (k
,v
) for k
,v
in content
.iteritems() if k
in filter_keys
)
619 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
620 data
={'vnf' : filtered_content
}
622 result
,content
= mydb
.get_table(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
623 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description'),
624 WHERE
={'vnfs.uuid': vnf_id
} )
626 print "nfvo.get_vnf_id error %d %s" % (result
, content
)
627 return (result
, content
)
629 print "nfvo.get_vnf_id vnf '%s' not found" % vnf_id
630 return (-HTTP_Not_Found
, "vnf %s not found" % vnf_id
)
632 data
['vnf']['VNFC'] = content
634 result
,content
= mydb
.get_table(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
635 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
636 WHERE
={'vnfs.uuid': vnf_id
} )
638 print "nfvo.get_vnf_id error %d %s" % (result
, content
)
639 return (result
, content
)
642 data
['vnf']['nets'] = []
644 data
['vnf']['nets'] = content
646 result
,content
= mydb
.get_table(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
647 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
648 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
649 WHERE
={'vnfs.uuid': vnf_id
},
650 WHERE_NOT
={'interfaces.external_name': None} )
653 print "nfvo.get_vnf_id error %d %s" % (result
, content
)
654 return (result
, content
)
657 data
['vnf']['external-connections'] = []
659 data
['vnf']['external-connections'] = content
663 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
665 if tenant_id
!= "any":
666 if not check_tenant(mydb
, tenant_id
):
667 print 'nfvo.delete_vnf() tenant %s not found' % tenant_id
668 return -HTTP_Not_Found
, 'Tenant %s not found' % tenant_id
669 # Get the URL of the VIM from the nfvo_tenant and the datacenter
670 result
, vims
= get_vim(mydb
, tenant_id
)
672 print "nfvo.delete_vnf() error. Datacenter not found"
677 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
679 if tenant_id
!= "any":
680 where_or
["tenant_id"] = tenant_id
681 where_or
["public"] = True
682 result
, content
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
684 return result
, content
685 vnf_id
= content
["uuid"]
687 # "Getting the list of flavors and tenants of the VNF"
688 result
,flavorList
= get_flavorlist(mydb
, vnf_id
)
692 print "delete_vnf error. No flavors found for the VNF id '%s'" % vnf_id
694 result
,imageList
= get_imagelist(mydb
, vnf_id
)
695 print "imageList", imageList
699 print "delete_vnf error. No images found for the VNF id '%s'" % vnf_id
701 result
, content
= mydb
.delete_row('vnfs', vnf_id
, tenant_id
)
703 return -HTTP_Not_Found
, content
707 print "delete_vnf error",result
, content
708 return result
, content
711 for flavor
in flavorList
:
712 #check if flavor is used by other vnf
713 r
,c
= mydb
.get_table(FROM
='vms', WHERE
={'flavor_id':flavor
} )
715 print 'delete_vnf_error. Not possible to delete VIM flavor "%s". %s' % (flavor
,c
)
716 undeletedItems
.append("flavor "+ flavor
["flavor_id"])
718 print 'Flavor %s not deleted because it is being used by another VNF %s' %(flavor
,str(c
))
720 #flavor not used, must be deleted
722 r
,c
= mydb
.get_table(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
725 if flavor_vim
["datacenter_id"] not in vims
:
727 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
729 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
730 result
, message
= myvim
.delete_tenant_flavor(flavor_vim
["vim_id"])
732 print 'delete_vnf_error. Not possible to delete VIM flavor "%s". Message: %s' % (flavor
,message
)
733 if result
!= -HTTP_Not_Found
:
734 undeletedItems
.append("flavor %s from VIM %s" % (flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
735 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
736 result
, content
= mydb
.delete_row('flavors', flavor
)
738 undeletedItems
.append("flavor %s" % flavor
)
740 for image
in imageList
:
741 #check if image is used by other vnf
742 r
,c
= mydb
.get_table(FROM
='vms', WHERE
={'image_id':image
} )
744 print 'delete_vnf_error. Not possible to delete VIM image "%s". %s' % (image
,c
)
745 undeletedItems
.append("image "+ image
["image_id"])
747 print 'Image %s not deleted because it is being used by another VNF %s' %(image
,str(c
))
749 #image not used, must be deleted
751 r
,c
= mydb
.get_table(FROM
='datacenters_images', WHERE
={'image_id':image
})
754 if image_vim
["datacenter_id"] not in vims
:
756 if image_vim
['created']=='false': #skip this image because not created by openmano
758 myvim
=vims
[ image_vim
["datacenter_id"] ]
759 result
, message
= myvim
.delete_tenant_image(image_vim
["vim_id"])
761 print 'delete_vnf_error. Not possible to delete VIM image "%s". Message: %s' % (image
,message
)
762 if result
!= -HTTP_Not_Found
:
763 undeletedItems
.append("image %s from VIM %s" % (image_vim
["vim_id"], image_vim
["datacenter_id"] ))
764 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
765 result
, content
= mydb
.delete_row('images', image
)
767 undeletedItems
.append("image %s" % image
)
770 return 200, "delete_vnf error. Undeleted: %s" %(undeletedItems)
774 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
775 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
779 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
780 myvim
= vims
.values()[0]
781 result
,servers
= myvim
.get_hosts_info()
783 return result
, servers
784 topology
= {'name':myvim
['name'] , 'servers': servers
}
785 return result
, topology
787 def get_hosts(mydb
, nfvo_tenant_id
):
788 result
, vims
= get_vim(mydb
, nfvo_tenant_id
)
792 return -HTTP_Not_Found
, "No datacenter found"
793 myvim
= vims
.values()[0]
794 result
,hosts
= myvim
.get_hosts()
797 print '==================='
798 print 'hosts '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False)
800 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
802 server
={'name':host
['name'], 'vms':[]}
803 for vm
in host
['instances']:
804 #get internal name and model
805 r
,c
= mydb
.get_table(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
806 WHERE
={'vim_vm_id':vm
['id']} )
808 print "nfvo.get_hosts virtual machine at VIM (%s) not found at tidnfvo" % vm
['id']
811 print "nfvo.get_hosts virtual machine at VIM (%s) error %d %s" % (vm
['id'], r
, c
)
813 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
814 datacenter
['Datacenters'][0]['servers'].append(server
)
815 #return -400, "en construccion"
817 #print 'datacenters '+ json.dumps(datacenter, indent=4)
818 return result
, datacenter
820 def new_scenario(mydb
, tenant_id
, topo
):
822 # result, vims = get_vim(mydb, tenant_id)
824 # return result, vims
826 if tenant_id
!= "any":
827 if not check_tenant(mydb
, tenant_id
):
828 print 'nfvo.new_scenario() tenant %s not found' % tenant_id
829 return -HTTP_Not_Found
, 'Tenant %s not found' % tenant_id
830 if "tenant_id" in topo
:
831 if topo
["tenant_id"] != tenant_id
:
832 print "nfvo.new_scenario() tenant '%s' not found" % tenant_id
833 return -HTTP_Unauthorized
, "VNF can not have a different tenant owner '%s', must be '%s'" %(topo
["tenant_id"], tenant_id
)
837 #1.1: get VNFs and external_networks (other_nets).
839 other_nets
={} #external_networks, bridge_networks and data_networkds
840 nodes
= topo
['topology']['nodes']
841 for k
in nodes
.keys():
842 if nodes
[k
]['type'] == 'VNF':
844 vnfs
[k
]['ifaces'] = {}
845 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
846 other_nets
[k
] = nodes
[k
]
847 other_nets
[k
]['external']=True
848 elif nodes
[k
]['type'] == 'network':
849 other_nets
[k
] = nodes
[k
]
850 other_nets
[k
]['external']=False
853 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
854 for name
,vnf
in vnfs
.items():
857 error_pos
= "'topology':'nodes':'" + name
+ "'"
859 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
860 WHERE_
['uuid'] = vnf
['vnf_id']
861 if 'VNF model' in vnf
:
862 error_text
+= " 'VNF model' " + vnf
['VNF model']
863 WHERE_
['name'] = vnf
['VNF model']
865 return -HTTP_Bad_Request
, "needed a 'vnf_id' or 'VNF model' at " + error_pos
866 r
,vnf_db
= mydb
.get_table(SELECT
=('uuid','name','description'), FROM
='vnfs', WHERE
=WHERE_
)
868 print "nfvo.new_scenario Error getting vnfs",r
,vnf_db
870 print "nfvo.new_scenario Error" + error_text
+ " is not present at database"
871 return -HTTP_Bad_Request
, "unknown" + error_text
+ " at " + error_pos
873 print "nfvo.new_scenario Error more than one" + error_text
+ " are present at database"
874 return -HTTP_Bad_Request
, "more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'"
875 vnf
['uuid']=vnf_db
[0]['uuid']
876 vnf
['description']=vnf_db
[0]['description']
877 #get external interfaces
878 r
,ext_ifaces
= mydb
.get_table(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
879 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
880 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
882 print "nfvo.new_scenario Error getting external interfaces of vnfs",r
,ext_ifaces
883 return -HTTP_Internal_Server_Error
, "Error getting external interfaces of vnfs: " + ext_ifaces
884 for ext_iface
in ext_ifaces
:
885 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
887 #1.4 get list of connections
888 conections
= topo
['topology']['connections']
890 for k
in conections
.keys():
891 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
892 ifaces_list
= conections
[k
]['nodes'].items()
893 elif type(conections
[k
]['nodes'])==list: #list with dictionary
895 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
896 for k2
in conection_pair_list
:
899 con_type
= conections
[k
].get("type", "link")
900 if con_type
!= "link":
902 return -HTTP_Bad_Request
, "format error. Reapeted network name at 'topology':'connections':'%s'" % (str(k
))
903 other_nets
[k
] = {'external': False}
904 if conections
[k
].get("graph"):
905 other_nets
[k
]["graph"] = conections
[k
]["graph"]
906 ifaces_list
.append( (k
, None) )
909 if con_type
== "external_network":
910 other_nets
[k
]['external'] = True
911 if conections
[k
].get("model"):
912 other_nets
[k
]["model"] = conections
[k
]["model"]
914 other_nets
[k
]["model"] = k
915 if con_type
== "dataplane_net" or con_type
== "bridge_net":
916 other_nets
[k
]["model"] = con_type
919 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)
920 #print set(ifaces_list)
921 #check valid VNF and iface names
922 for iface
in ifaces_list
:
923 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
924 return -HTTP_Bad_Request
, "format error. Invalid VNF name at 'topology':'connections':'%s':'nodes':'%s'" % (str(k
), iface
[0])
925 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
926 return -HTTP_Bad_Request
, "format error. Invalid interface name at 'topology':'connections':'%s':'nodes':'%s':'%s'" % (str(k
), iface
[0], iface
[1])
928 #1.5 unify connections from the pair list to a consolidated list
930 while index
< len(conections_list
):
932 while index2
< len(conections_list
):
933 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
934 conections_list
[index
] |
= conections_list
[index2
]
935 del conections_list
[index2
]
938 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
940 #for k in conections_list:
945 #1.6 Delete non external nets
946 # for k in other_nets.keys():
947 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
948 # for con in conections_list:
950 # for index in range(0,len(con)):
951 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
952 # for index in delete_indexes:
955 #1.7: Check external_ports are present at database table datacenter_nets
956 for k
,net
in other_nets
.items():
957 error_pos
= "'topology':'nodes':'" + k
+ "'"
958 if net
['external']==False:
959 if 'name' not in net
:
961 if 'model' not in net
:
962 return -HTTP_Bad_Request
, "needed a 'model' at " + error_pos
963 if net
['model']=='bridge_net':
964 net
['type']='bridge';
965 elif net
['model']=='dataplane_net':
968 return -HTTP_Bad_Request
, "unknown 'model' '"+ net
['model'] +"' at " + error_pos
970 #IF we do not want to check that external network exist at datacenter
975 # if 'net_id' in net:
976 # error_text += " 'net_id' " + net['net_id']
977 # WHERE_['uuid'] = net['net_id']
979 # error_text += " 'model' " + net['model']
980 # WHERE_['name'] = net['model']
981 # if len(WHERE_) == 0:
982 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
983 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
984 # FROM='datacenter_nets', WHERE=WHERE_ )
986 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
988 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
989 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
991 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
992 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
993 # other_nets[k].update(net_db[0])
996 net_nb
=0 #Number of nets
997 for con
in conections_list
:
998 #check if this is connected to a external net
1002 for index
in range(0,len(con
)):
1003 #check if this is connected to a external net
1004 for net_key
in other_nets
.keys():
1005 if con
[index
][0]==net_key
:
1006 if other_net_index
>=0:
1007 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1008 print "nfvo.new_scenario " + error_text
1009 return -HTTP_Bad_Request
, error_text
1011 other_net_index
= index
1012 net_target
= net_key
1014 #print "other_net_index", other_net_index
1016 if other_net_index
>=0:
1017 del con
[other_net_index
]
1018 #IF we do not want to check that external network exist at datacenter
1019 if other_nets
[net_target
]['external'] :
1020 if "name" not in other_nets
[net_target
]:
1021 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1022 if other_nets
[net_target
]["type"] == "external_network":
1023 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1024 other_nets
[net_target
]["type"] = "data"
1026 other_nets
[net_target
]["type"] = "bridge"
1028 # if other_nets[net_target]['external'] :
1029 # 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
1030 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1031 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1032 # print "nfvo.new_scenario " + error_text
1033 # return -HTTP_Bad_Request, error_text
1036 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1039 net_type_bridge
=False
1041 net_target
= "__-__net"+str(net_nb
)
1042 net_list
[net_target
] = {'name': "net-"+str(net_nb
), 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1045 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1046 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1047 if iface_type
=='mgmt' or iface_type
=='bridge':
1048 net_type_bridge
= True
1050 net_type_data
= True
1051 if net_type_bridge
and net_type_data
:
1052 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1053 print "nfvo.new_scenario " + error_text
1054 return -HTTP_Bad_Request
, error_text
1055 elif net_type_bridge
:
1058 type_
='data' if len(con
)>2 else 'ptp'
1059 net_list
[net_target
]['type'] = type_
1062 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1063 print "nfvo.new_scenario " + error_text
1065 return -HTTP_Bad_Request
, error_text
1067 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1068 #1.8.1 obtain management net
1069 r
,mgmt_net
= mydb
.get_table(SELECT
=('uuid','name','description','type','shared'),
1070 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1071 #1.8.2 check all interfaces from all vnfs
1073 add_mgmt_net
= False
1074 for vnf
in vnfs
.values():
1075 for iface
in vnf
['ifaces'].values():
1076 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1077 #iface not connected
1078 iface
['net_key'] = 'mgmt'
1080 if add_mgmt_net
and 'mgmt' not in net_list
:
1081 net_list
['mgmt']=mgmt_net
[0]
1082 net_list
['mgmt']['external']=True
1083 net_list
['mgmt']['graph']={'visible':False}
1085 net_list
.update(other_nets
)
1087 print 'net_list', net_list
1092 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1093 r
,c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1094 'tenant_id':tenant_id
, 'name':topo
['name'],
1095 'description':topo
.get('description',topo
['name']),
1096 'public': topo
.get('public', False)
1101 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
):
1102 scenario
= scenario_dict
["scenario"]
1103 if tenant_id
!= "any":
1104 if not check_tenant(mydb
, tenant_id
):
1105 print 'nfvo.new_scenario_v02() tenant %s not found' % tenant_id
1106 return -HTTP_Not_Found
, 'Tenant %s not found' % tenant_id
1107 if "tenant_id" in scenario
:
1108 if scenario
["tenant_id"] != tenant_id
:
1109 print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1110 return -HTTP_Unauthorized
, "VNF can not have a different tenant owner '%s', must be '%s'" %(scenario
["tenant_id"], tenant_id
)
1114 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1115 for name
,vnf
in scenario
["vnfs"].iteritems():
1118 error_pos
= "'topology':'nodes':'" + name
+ "'"
1120 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1121 WHERE_
['uuid'] = vnf
['vnf_id']
1122 if 'vnf_name' in vnf
:
1123 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1124 WHERE_
['name'] = vnf
['vnf_name']
1125 if len(WHERE_
) == 0:
1126 return -HTTP_Bad_Request
, "needed a 'vnf_id' or 'VNF model' at " + error_pos
1127 r
,vnf_db
= mydb
.get_table(SELECT
=('uuid','name','description'), FROM
='vnfs', WHERE
=WHERE_
)
1129 print "nfvo.new_scenario Error getting vnfs",r
,vnf_db
1131 print "nfvo.new_scenario Error" + error_text
+ " is not present at database"
1132 return -HTTP_Bad_Request
, "unknown" + error_text
+ " at " + error_pos
1134 print "nfvo.new_scenario Error more than one" + error_text
+ " are present at database"
1135 return -HTTP_Bad_Request
, "more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'"
1136 vnf
['uuid']=vnf_db
[0]['uuid']
1137 vnf
['description']=vnf_db
[0]['description']
1139 #get external interfaces
1140 r
,ext_ifaces
= mydb
.get_table(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1141 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1142 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1144 print "nfvo.new_scenario Error getting external interfaces of vnfs",r
,ext_ifaces
1145 return -HTTP_Internal_Server_Error
, "Error getting external interfaces of vnfs: " + ext_ifaces
1146 for ext_iface
in ext_ifaces
:
1147 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1149 #2: Insert net_key at every vnf interface
1150 for net_name
,net
in scenario
["networks"].iteritems():
1151 net_type_bridge
=False
1153 for iface_dict
in net
["interfaces"]:
1154 for vnf
,iface
in iface_dict
.iteritems():
1155 if vnf
not in scenario
["vnfs"]:
1156 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1157 print "nfvo.new_scenario_v02 " + error_text
1158 return -HTTP_Bad_Request
, error_text
1159 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1160 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1161 print "nfvo.new_scenario_v02 " + error_text
1162 return -HTTP_Bad_Request
, error_text
1163 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1164 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1165 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1166 print "nfvo.new_scenario_v02 " + error_text
1167 return -HTTP_Bad_Request
, error_text
1168 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1169 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1170 if iface_type
=='mgmt' or iface_type
=='bridge':
1171 net_type_bridge
= True
1173 net_type_data
= True
1174 if net_type_bridge
and net_type_data
:
1175 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1176 print "nfvo.new_scenario " + error_text
1177 return -HTTP_Bad_Request
, error_text
1178 elif net_type_bridge
:
1181 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1183 net
['name'] = net_name
1184 net
['external'] = net
.get('external', False)
1186 #3: insert at database
1187 scenario
["nets"] = scenario
["networks"]
1188 scenario
['tenant_id'] = tenant_id
1189 r
,c
= mydb
.new_scenario( scenario
)
1193 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1194 data
["uuid"] = scenario_id
1195 data
["tenant_id"] = tenant_id
1196 r
,c
= mydb
.edit_scenario( data
)
1199 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1200 print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1201 datacenter_id
= None
1202 datacenter_name
=None
1203 if datacenter
!= None:
1204 if utils
.check_valid_uuid(datacenter
):
1205 datacenter_id
= datacenter
1207 datacenter_name
= datacenter
1208 result
, vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
)
1210 print "start_scenario error. Datacenter not found"
1213 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
1215 print "start_scenario error. Several datacenters available, you must concrete"
1216 return -HTTP_Bad_Request
, "Several datacenters available, you must concrete"
1217 myvim
= vims
.values()[0]
1218 myvim_tenant
= myvim
['tenant_id']
1219 datacenter_id
= myvim
['id']
1220 datacenter_name
= myvim
['name']
1221 datacenter_tenant_id
= myvim
['config']['datacenter_tenant_id']
1224 print "Checking that the scenario_id exists and getting the scenario dictionary"
1225 result
, scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1227 print "start_scenario error. Error interacting with NFVO DB"
1228 return result
, scenarioDict
1230 print "start_scenario error. Scenario not found"
1231 return result
, scenarioDict
1233 scenarioDict
['datacenter_tenant_id'] = datacenter_tenant_id
1234 scenarioDict
['datacenter_id'] = datacenter_id
1235 print '================scenarioDict======================='
1236 #print json.dumps(scenarioDict, indent=4)
1237 print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name
,scenarioDict
['name'])
1239 print "Scenario %s: consisting of %d VNF(s)" % (scenarioDict
['name'],len(scenarioDict
['vnfs']))
1240 print yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)
1242 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1243 auxNetDict
['scenario'] = {}
1245 print "1. Creating new nets (sce_nets) in the VIM"
1246 for sce_net
in scenarioDict
['nets']:
1247 print "Net name: %s. Description: %s" % (sce_net
["name"], sce_net
["description"])
1249 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1250 myNetName
= myNetName
[0:255] #limit length
1251 myNetType
= sce_net
['type']
1253 myNetDict
["name"] = myNetName
1254 myNetDict
["type"] = myNetType
1255 myNetDict
["tenant_id"] = myvim_tenant
1257 #We should use the dictionary as input parameter for new_tenant_network
1259 if not sce_net
["external"]:
1260 result
, network_id
= myvim
.new_tenant_network(myNetName
, myNetType
)
1262 print "Error creating network: %s." %network_id
1263 _
, message
= rollback(mydb
, vims
, rollbackList
)
1264 return result
, "Error creating network: "+ network_id
+ "."+message
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 print "nfvo.start_scenario: " + error_text
1275 return -HTTP_Bad_Request
, error_text
1276 print "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 print "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_tenant_network
1295 result
, network_id
= myvim
.new_tenant_network(myNetName
, myNetType
)
1297 error_text
="Error creating network: %s." % network_id
1298 _
, message
= rollback(mydb
, vims
, rollbackList
)
1299 error_text
+= message
1300 print "start_scenario: " + error_text
1301 return result
, error_text
1302 print "VIM network id for scenario %s: %s" % (scenarioDict
['name'],network_id
)
1303 net
['vim_id'] = network_id
1304 if sce_vnf
['uuid'] not in auxNetDict
:
1305 auxNetDict
[sce_vnf
['uuid']] = {}
1306 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1307 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1310 print yaml
.safe_dump(auxNetDict
, indent
=4, default_flow_style
=False)
1312 print "3. Creating new vm instances in the VIM"
1313 #myvim.new_tenant_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1315 for sce_vnf
in scenarioDict
['vnfs']:
1316 for vm
in sce_vnf
['vms']:
1319 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1320 myVMDict
['name'] = "%s.%s.%d" % (instance_scenario_name
,sce_vnf
['name'],i
)
1321 #myVMDict['description'] = vm['description']
1322 myVMDict
['description'] = myVMDict
['name'][0:99]
1324 myVMDict
['start'] = "no"
1325 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1326 print "VM name: %s. Description: %s" % (myVMDict
['name'], myVMDict
['name'])
1328 #create image at vim in case it not exist
1329 res
, image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1331 print "start_scenario error getting image", image_dict
1332 return res
, image_dict
1333 res
, image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1335 print "start_scenario error adding image to VIM", image_dict
1336 return res
, image_id
1337 vm
['vim_image_id'] = image_id
1339 #create flavor at vim in case it not exist
1340 res
, flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1342 print "start_scenario error getting flavor", flavor_dict
1343 return res
, flavor_dict
1344 if flavor_dict
['extended']!=None:
1345 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1346 res
, flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1348 print "start_scenario error adding flavor to VIM", flavor_dict
1349 return res
, flavor_id
1350 vm
['vim_flavor_id'] = flavor_id
1353 myVMDict
['imageRef'] = vm
['vim_image_id']
1354 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1355 myVMDict
['networks'] = []
1356 for iface
in vm
['interfaces']:
1358 if iface
['type']=="data":
1359 netDict
['type'] = iface
['model']
1360 elif "model" in iface
and iface
["model"]!=None:
1361 netDict
['model']=iface
['model']
1362 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1363 #discover type of interface looking at flavor
1364 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1365 for flavor_iface
in numa
.get('interfaces',[]):
1366 if flavor_iface
.get('name') == iface
['internal_name']:
1367 if flavor_iface
['dedicated'] == 'yes':
1368 netDict
['type']="PF" #passthrough
1369 elif flavor_iface
['dedicated'] == 'no':
1370 netDict
['type']="VF" #siov
1371 elif flavor_iface
['dedicated'] == 'yes:sriov':
1372 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1373 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1375 netDict
["use"]=iface
['type']
1376 if netDict
["use"]=="data" and not netDict
.get("type"):
1377 #print "netDict", netDict
1378 #print "iface", iface
1379 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'])
1380 if flavor_dict
.get('extended')==None:
1381 return -HTTP_Conflict
, e_text
+ "After database migration some information is not available. \
1382 Try to delete and create the scenarios and VNFs again"
1384 return -HTTP_Internal_Server_Error
, e_text
1385 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1386 netDict
["type"]="virtual"
1387 if "vpci" in iface
and iface
["vpci"] is not None:
1388 netDict
['vpci'] = iface
['vpci']
1389 if "mac" in iface
and iface
["mac"] is not None:
1390 netDict
['mac_address'] = iface
['mac']
1391 netDict
['name'] = iface
['internal_name']
1392 if iface
['net_id'] is None:
1393 for vnf_iface
in sce_vnf
["interfaces"]:
1396 if vnf_iface
['interface_id']==iface
['uuid']:
1397 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1400 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1401 #skip bridge ifaces not connected to any net
1402 #if 'net_id' not in netDict or netDict['net_id']==None:
1404 myVMDict
['networks'].append(netDict
)
1405 print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1406 print myVMDict
['name']
1407 print "networks", yaml
.safe_dump(myVMDict
['networks'], indent
=4, default_flow_style
=False)
1408 print "interfaces", yaml
.safe_dump(vm
['interfaces'], indent
=4, default_flow_style
=False)
1409 print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1410 result
, vm_id
= myvim
.new_tenant_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1411 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1413 error_text
= "Error creating vm instance: %s." % vm_id
1414 _
, message
= rollback(mydb
, vims
, rollbackList
)
1415 error_text
+= message
1416 print "start_scenario: " + error_text
1417 return result
, error_text
1418 print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict
['name'],vm_id
)
1419 vm
['vim_id'] = vm_id
1420 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1421 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1422 for net
in myVMDict
['networks']:
1424 for iface
in vm
['interfaces']:
1425 if net
["name"]==iface
["internal_name"]:
1426 iface
["vim_id"]=net
["vim_id"]
1429 print "==================Deployment done=========="
1430 print yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)
1431 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1432 result
,c
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1434 error_text
= c
+ "."
1435 _
, message
= rollback(mydb
, vims
, rollbackList
)
1436 error_text
+= message
1437 print "start_scenario: " + error_text
1438 return result
, error_text
1440 return mydb
.get_instance_scenario(c
)
1442 def create_instance(mydb
, tenant_id
, instance_dict
):
1443 print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1444 scenario
= instance_dict
["scenario"]
1445 datacenter_id
= None
1446 datacenter_name
=None
1447 datacenter
= instance_dict
.get("datacenter")
1449 if utils
.check_valid_uuid(datacenter
):
1450 datacenter_id
= datacenter
1452 datacenter_name
= datacenter
1453 result
, vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
=None)
1455 print "start_scenario error. Datacenter not found"
1458 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
1460 print "start_scenario error. Several datacenters available, you must concrete"
1461 return -HTTP_Bad_Request
, "Several datacenters available, you must concrete"
1462 myvim
= vims
.values()[0]
1463 #myvim_tenant = myvim['tenant_id']
1464 datacenter_id
= myvim
['id']
1465 datacenter_name
= myvim
['name']
1466 datacenter_tenant_id
= myvim
['config']['datacenter_tenant_id']
1469 print "Checking that the scenario exists and getting the scenario dictionary"
1470 result
, scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_id
)
1472 print "start_scenario error. Error interacting with NFVO DB"
1473 return result
, scenarioDict
1475 print "start_scenario error. Scenario not found"
1476 return result
, scenarioDict
1478 scenarioDict
['datacenter_tenant_id'] = datacenter_tenant_id
1479 scenarioDict
['datacenter_id'] = datacenter_id
1481 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1482 auxNetDict
['scenario'] = {}
1484 print "scenario dict: ",yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)
1485 instance_name
= instance_dict
["name"]
1486 instance_description
= instance_dict
.get("description")
1488 #0 check correct parameters
1489 for descriptor_net
in instance_dict
.get("networks",{}).keys():
1491 for scenario_net
in scenarioDict
['nets']:
1492 if descriptor_net
== scenario_net
["name"]:
1496 raise NfvoException(-HTTP_Bad_Request
, "Invalid scenario network name '%s' at instance:networks" % descriptor_net
)
1497 for descriptor_vnf
in instance_dict
.get("vnfs",{}).keys():
1499 for scenario_vnf
in scenarioDict
['vnfs']:
1500 if descriptor_vnf
== scenario_vnf
['name']:
1504 raise NfvoException(-HTTP_Bad_Request
, "Invalid vnf name '%s' at instance:vnfs" % descriptor_vnf
)
1506 #1. Creating new nets (sce_nets) in the VIM"
1507 for sce_net
in scenarioDict
['nets']:
1508 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
1509 net_name
= descriptor_net
.get("name")
1510 net_type
= sce_net
['type']
1511 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
1512 if sce_net
["external"]:
1514 net_name
= sce_net
["name"]
1515 if "netmap-use" in descriptor_net
or "netmap-create" in descriptor_net
:
1516 create_network
= False
1517 lookfor_network
= False
1518 if "netmap-use" in descriptor_net
:
1519 lookfor_network
= True
1520 if utils
.check_valid_uuid(descriptor_net
["netmap-use"]):
1521 filter_text
= "scenario id '%s'" % descriptor_net
["netmap-use"]
1522 lookfor_filter
["id"] = descriptor_net
["netmap-use"]
1524 filter_text
= "scenario name '%s'" % descriptor_net
["netmap-use"]
1525 lookfor_filter
["name"] = descriptor_net
["netmap-use"]
1526 if "netmap-create" in descriptor_net
:
1527 create_network
= True
1528 net_vim_name
= net_name
1529 if descriptor_net
["netmap-create"]:
1530 net_vim_name
= descriptor_net
["netmap-create"]
1532 elif sce_net
['vim_id'] != None:
1533 #there is a netmap at datacenter_nets database
1534 create_network
= False
1535 lookfor_network
= True
1536 lookfor_filter
["id"] = sce_net
['vim_id']
1537 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
1538 #look for network at datacenter and return error
1540 #There is not a netmap, look at datacenter for a net with this name and create if not found
1541 create_network
= True
1542 lookfor_network
= True
1543 lookfor_filter
["name"] = sce_net
["name"]
1544 net_vim_name
= sce_net
["name"]
1545 filter_text
= "scenario name '%s'" % sce_net
["name"]
1548 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
1549 net_name
= net_name
[:255] #limit length
1550 net_vim_name
= net_name
1551 create_network
= True
1552 lookfor_network
= False
1555 result
, vim_nets
= myvim
.get_network_list(filter_dict
=lookfor_filter
)
1557 raise NfvoException(result
, "Not possible to get vim network list " + vim_nets
)
1558 elif len(vim_nets
) > 1:
1559 raise NfvoException(-HTTP_Bad_Request
, "More than one candidate VIM network found for " + filter_text
)
1560 elif len(vim_nets
) == 0:
1561 if not create_network
:
1562 raise NfvoException(-HTTP_Bad_Request
, "No candidate VIM network found for " + filter_text
)
1564 sce_net
['vim_id'] = vim_nets
[0]['id']
1565 auxNetDict
['scenario'][sce_net
['uuid']] = vim_nets
[0]['id']
1566 create_network
= False
1568 #if network is not external
1569 result
, network_id
= myvim
.new_tenant_network(net_vim_name
, net_type
)
1571 raise NfvoException(result
, "Error creating vim network " + network_id
)
1572 sce_net
['vim_id'] = network_id
1573 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1574 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1576 #2. Creating new nets (vnf internal nets) in the VIM"
1577 #For each vnf net, we create it and we add it to instanceNetlist.
1578 for sce_vnf
in scenarioDict
['vnfs']:
1579 for net
in sce_vnf
['nets']:
1580 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
1581 net_name
= descriptor_net
.get("name")
1583 net_name
= "%s.%s" %(instance_name
, net
["name"])
1584 net_name
= net_name
[:255] #limit length
1585 net_type
= net
['type']
1586 result
, network_id
= myvim
.new_tenant_network(net_name
, net_type
)
1588 raise NfvoException(result
, "Error creating vim network " + network_id
)
1589 net
['vim_id'] = network_id
1590 if sce_vnf
['uuid'] not in auxNetDict
:
1591 auxNetDict
[sce_vnf
['uuid']] = {}
1592 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1593 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1596 print yaml
.safe_dump(auxNetDict
, indent
=4, default_flow_style
=False)
1598 #3. Creating new vm instances in the VIM
1599 #myvim.new_tenant_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1600 for sce_vnf
in scenarioDict
['vnfs']:
1602 for vm
in sce_vnf
['vms']:
1605 myVMDict
['name'] = "%s.%s.%d" % (instance_name
,sce_vnf
['name'],i
)
1606 myVMDict
['description'] = myVMDict
['name'][0:99]
1608 # myVMDict['start'] = "no"
1609 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1610 #create image at vim in case it not exist
1611 res
, image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1613 raise NfvoException(result
, "Error getting VIM image "+ image_dict
)
1614 res
, image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1616 raise NfvoException(result
, "Error adding image to VIM " + image_dict
)
1617 vm
['vim_image_id'] = image_id
1619 #create flavor at vim in case it not exist
1620 res
, flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1622 raise NfvoException(result
, "Error getting VIM flavor "+ flavor_dict
)
1623 if flavor_dict
['extended']!=None:
1624 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1625 res
, flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1627 raise NfvoException(result
, "Error adding flavor to VIM" + flavor_dict
)
1628 vm
['vim_flavor_id'] = flavor_id
1630 myVMDict
['imageRef'] = vm
['vim_image_id']
1631 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1632 myVMDict
['networks'] = []
1633 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
1634 for iface
in vm
['interfaces']:
1636 if iface
['type']=="data":
1637 netDict
['type'] = iface
['model']
1638 elif "model" in iface
and iface
["model"]!=None:
1639 netDict
['model']=iface
['model']
1640 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1641 #discover type of interface looking at flavor
1642 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1643 for flavor_iface
in numa
.get('interfaces',[]):
1644 if flavor_iface
.get('name') == iface
['internal_name']:
1645 if flavor_iface
['dedicated'] == 'yes':
1646 netDict
['type']="PF" #passthrough
1647 elif flavor_iface
['dedicated'] == 'no':
1648 netDict
['type']="VF" #siov
1649 elif flavor_iface
['dedicated'] == 'yes:sriov':
1650 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1651 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1653 netDict
["use"]=iface
['type']
1654 if netDict
["use"]=="data" and not netDict
.get("type"):
1655 #print "netDict", netDict
1656 #print "iface", iface
1657 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'])
1658 if flavor_dict
.get('extended')==None:
1659 raise NfvoException(-HTTP_Conflict
, e_text
+ "After database migration some information is not available. \
1660 Try to delete and create the scenarios and VNFs again")
1662 raise NfvoException(-HTTP_Internal_Server_Error
, e_text
)
1663 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1664 netDict
["type"]="virtual"
1665 if "vpci" in iface
and iface
["vpci"] is not None:
1666 netDict
['vpci'] = iface
['vpci']
1667 if "mac" in iface
and iface
["mac"] is not None:
1668 netDict
['mac_address'] = iface
['mac']
1669 netDict
['name'] = iface
['internal_name']
1670 if iface
['net_id'] is None:
1671 for vnf_iface
in sce_vnf
["interfaces"]:
1674 if vnf_iface
['interface_id']==iface
['uuid']:
1675 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1678 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1679 #skip bridge ifaces not connected to any net
1680 #if 'net_id' not in netDict or netDict['net_id']==None:
1682 myVMDict
['networks'].append(netDict
)
1683 print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1684 print myVMDict
['name']
1685 print "networks", yaml
.safe_dump(myVMDict
['networks'], indent
=4, default_flow_style
=False)
1686 print "interfaces", yaml
.safe_dump(vm
['interfaces'], indent
=4, default_flow_style
=False)
1687 print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1688 result
, vm_id
= myvim
.new_tenant_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1689 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1691 raise NfvoException(result
, "Error creating VIM instance" + vm_id
)
1692 vm
['vim_id'] = vm_id
1693 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1694 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1695 for net
in myVMDict
['networks']:
1697 for iface
in vm
['interfaces']:
1698 if net
["name"]==iface
["internal_name"]:
1699 iface
["vim_id"]=net
["vim_id"]
1701 print "==================Deployment done=========="
1702 print yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)
1703 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1704 result
,c
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
1706 raise NfvoException(result
, c
)
1708 return mydb
.get_instance_scenario(c
)
1709 except NfvoException
as e
:
1710 error_text
= str(e
) + ". "
1711 _
, message
= rollback(mydb
, vims
, rollbackList
)
1712 error_text
+= message
1713 print "create_instance: " + error_text
1714 return e
.error_code
, error_text
1716 def delete_instance(mydb
, tenant_id
, instance_id
):
1717 print "Checking that the instance_id exists and getting the instance dictionary"
1718 result
, instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
1720 print "nfvo.delete_instance() error. Error getting info from database"
1721 return result
, instanceDict
1723 print "delete_instance error. Instance not found"
1724 return result
, instanceDict
1725 print yaml
.safe_dump(instanceDict
, indent
=4, default_flow_style
=False)
1726 tenant_id
= instanceDict
["tenant_id"]
1727 print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1728 result
, vims
= get_vim(mydb
, tenant_id
, instanceDict
['datacenter_id'])
1730 print "nfvo.delete_instance() error. Datacenter not found"
1733 print "!!!!!! nfvo.delete_instance() datacenter not found!!!!"
1736 myvim
= vims
.values()[0]
1739 #1. Delete from Database
1741 #result,c = mydb.delete_row('instance_scenarios', instance_id, nfvo_tenant)
1742 result
,c
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
1748 error_msg
= "Not possible to delete VIM VMs and networks. Datacenter not found at database!!!"
1754 for sce_vnf
in instanceDict
['vnfs']:
1757 for vm
in sce_vnf
['vms']:
1758 result
, vm_id
= myvim
.delete_tenant_vminstance(vm
['vim_vm_id'])
1760 error_msg
+="\n Error: " + str(-result
) + " VM id=" + vm
['vim_vm_id']
1761 #if result != -HTTP_Not_Found: vm_fail_list.append(vm)
1762 print "Error " + str(-result
) + " deleting VM instance '" + vm
['name'] + "', uuid '" + vm
['uuid'] + "', VIM id '" + vm
['vim_vm_id'] + "', from VNF_id '" + sce_vnf
['vnf_id'] + "':" + vm_id
1766 for net
in instanceDict
['nets']:
1768 continue #skip not created nets
1771 result
, net_id
= myvim
.delete_tenant_network(net
['vim_net_id'])
1773 error_msg
+= "\n Error: " + str(-result
) + " NET id=" + net
['vim_net_id']
1774 #if result == -HTTP_Not_Found: net_fail_list.append(net)
1775 print "Error " + str(-result
) + " deleting NET uuid '" + net
['uuid'] + "', VIM id '" + net
['vim_net_id'] + "':" + net_id
1777 if len(error_msg
)>0:
1778 return 1, 'instance ' + instance_id
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
1780 return 1, 'instance ' + instance_id
+ ' deleted'
1782 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
1783 '''Refreshes a scenario instance. It modifies instanceDict'''
1785 - 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
1788 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
1789 print "nfvo.refresh_instance begins"
1790 #print json.dumps(instanceDict, indent=4)
1792 print "Getting the VIM URL and the VIM tenant_id"
1793 result
, vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
1795 print "nfvo.refresh_instance() error. Datacenter not found"
1798 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(instanceDict
['datacenter_id'])
1799 myvim
= vims
.values()[0]
1801 # 1. Getting the status of all VMs
1804 for sce_vnf
in instanceDict
['vnfs']:
1805 for vm
in sce_vnf
['vms']:
1806 vmDict
[vm
['vim_vm_id']]=None
1809 # 2. Getting the status of all nets
1810 # TODO: update nets inside a vnf
1811 for net
in instanceDict
['nets']:
1812 #if net['external']:
1813 # continue #skip not created nets
1814 netDict
[net
['vim_net_id']]=None
1816 # 3. Refresh the status of VMs and nets from VIM. IT updates vmDict and netDict
1817 result
, refresh_message
= myvim
.refresh_tenant_vms_and_nets(vmDict
, netDict
)
1819 return result
, refresh_message
1821 # 4. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
1822 vms_updated
= [] #List of VM instance uuids in openmano that were updated
1824 for sce_vnf
in instanceDict
['vnfs']:
1825 for vm
in sce_vnf
['vms']:
1826 vm_id
= vm
['vim_vm_id']
1827 interfaces
= vmDict
[vm_id
].pop('interfaces', [])
1828 #4.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
1829 has_mgmt_iface
= False
1830 for iface
in vm
["interfaces"]:
1831 if iface
["type"]=="mgmt":
1832 has_mgmt_iface
= True
1833 if vmDict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
1834 vmDict
[vm_id
]['status'] = "ACTIVE"
1835 if vm
['status'] != vmDict
[vm_id
]['status'] or vm
.get('error_msg')!=vmDict
[vm_id
].get('error_msg') or vm
.get('vim_info')!=vmDict
[vm_id
].get('vim_info'):
1836 vm
['status'] = vmDict
[vm_id
]['status']
1837 vm
['error_msg'] = vmDict
[vm_id
].get('error_msg')
1838 vm
['vim_info'] = vmDict
[vm_id
].get('vim_info')
1839 # 4.1. Update in openmano DB the VMs whose status changed
1840 result2
, _
= mydb
.update_rows('instance_vms', UPDATE
=vmDict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
1842 vms_notupdated
.append(vm
["uuid"])
1844 vms_updated
.append(vm
["uuid"])
1845 # 4.2. Update in openmano DB the interface VMs
1846 for interface
in interfaces
:
1847 #translate from vim_net_id to instance_net_id
1849 for net
in instanceDict
['nets']:
1850 if net
["vim_net_id"] == interface
["vim_net_id"]:
1851 network_id
= net
["uuid"]
1855 del interface
["vim_net_id"]
1856 result2
, _
= mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
1858 print "nfvo.refresh_instance error with vm=%s, interface_net_id=%s" % (vm
["uuid"], network_id
)
1859 # 5. Update the status of nets in the instanceDict, while collects the nets whose status changed
1860 nets_updated
= [] #List of net instance uuids in openmano that were updated
1862 # TODO: update nets inside a vnf
1863 for net
in instanceDict
['nets']:
1864 net_id
= net
['vim_net_id']
1865 if net
['status'] != netDict
[net_id
]['status'] or net
.get('error_msg')!=netDict
[net_id
].get('error_msg') or net
.get('vim_info')!=netDict
[net_id
].get('vim_info'):
1866 net
['status'] = netDict
[net_id
]['status']
1867 net
['error_msg'] = netDict
[net_id
].get('error_msg')
1868 net
['vim_info'] = netDict
[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
=netDict
[net_id
], WHERE
={'uuid':net
["uuid"]})
1872 nets_notupdated
.append(net
["uuid"])
1874 nets_updated
.append(net
["uuid"])
1876 # Returns appropriate output
1877 print "nfvo.refresh_instance finishes"
1878 print "VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s" \
1879 % (str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
1880 instance_id
= instanceDict
['uuid']
1881 error_msg
=refresh_message
1882 if len(vms_notupdated
)+len(nets_notupdated
)>0:
1883 if len(refresh_message
)>0:
1885 error_msg
+= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
1886 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
1888 return 0, 'Scenario instance ' + instance_id
+ ' refreshed. ' + error_msg
1890 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
1891 print "Checking that the instance_id exists and getting the instance dictionary"
1892 result
, instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
1894 print "nfvo.instance_action() error. Error getting info from database"
1895 return result
, instanceDict
1897 print "instance_action error. Instance not found"
1898 return -HTTP_Not_Found
, "instance %s not found" % instance_id
1899 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
1901 print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1902 result
, vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
1904 print "nfvo.instance_action() error. Datacenter not found"
1907 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(instanceDict
['datacenter_id'])
1908 myvim
= vims
.values()[0]
1911 input_vnfs
= action_dict
.pop("vnfs", [])
1912 input_vms
= action_dict
.pop("vms", [])
1913 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
1917 for sce_vnf
in instanceDict
['vnfs']:
1918 for vm
in sce_vnf
['vms']:
1919 if not action_over_all
:
1920 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
1921 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
1923 result
, data
= myvim
.action_tenant_vminstance(vm
['vim_vm_id'], action_dict
)
1925 vm_result
[ vm
['uuid'] ] = {"vim_result": -result
, "name":vm
['name'], "description": data
}
1928 if "console" in action_dict
:
1929 if data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
1930 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
1931 "description": "this console is only reachable by local interface",
1936 #print "console data", data
1937 r2
, console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
1939 vm_result
[ vm
['uuid'] ] = {"vim_result": -r2
, "name":vm
['name'], "description": console_thread
}
1941 vm_result
[ vm
['uuid'] ] = {"vim_result": result
,
1942 "description": "%s//%s:%d/%s" %(data
["protocol"], console_thread
.host
, console_thread
.port
, data
["suffix"]),
1947 vm_result
[ vm
['uuid'] ] = {"vim_result": result
, "description": "ok", "name":vm
['name']}
1950 if vm_ok
==0: #all goes wrong
1955 def create_or_use_console_proxy_thread(console_server
, console_port
):
1956 #look for a non-used port
1957 console_thread_key
= console_server
+ ":" + str(console_port
)
1958 if console_thread_key
in global_config
["console_thread"]:
1959 #global_config["console_thread"][console_thread_key].start_timeout()
1960 return 1, global_config
["console_thread"][console_thread_key
]
1962 for port
in global_config
["console_port_iterator"]():
1963 print "create_or_use_console_proxy_thread() port:", port
1964 if port
in global_config
["console_ports"]:
1967 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
1969 global_config
["console_thread"][console_thread_key
] = clithread
1970 global_config
["console_ports"][port
] = console_thread_key
1972 except cli
.ConsoleProxyExceptionPortUsed
as e
:
1973 #port used, try with onoher
1975 except cli
.ConsoleProxyException
as e
:
1977 return -1, "Not found any free 'http_console_ports'"
1979 def check_tenant(mydb
, tenant_id
):
1980 '''check that tenant exists at database'''
1981 result
, _
= mydb
.get_table(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
1982 if result
<=0: return False
1985 def new_tenant(mydb
, tenant_dict
):
1986 result
, tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, None, add_uuid
=True, log
=True)
1988 return result
, tenant_id
1989 return 200,tenant_id
1991 def delete_tenant(mydb
, tenant
):
1992 #get nfvo_tenant info
1993 result
,tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
1995 return result
, tenant_dict
1997 result
, tenant_id
= mydb
.delete_row("nfvo_tenants", tenant_dict
['uuid'], None)
1999 return result
, tenant_id
2000 return 200, tenant_dict
['uuid']
2002 def new_datacenter(mydb
, datacenter_descriptor
):
2003 if "config" in datacenter_descriptor
:
2004 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2005 result
, datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, None, add_uuid
=True, log
=True)
2007 return result
, datacenter_id
2008 return 200,datacenter_id
2010 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2011 #obtain data, check that only one exist
2012 result
, content
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2014 return result
, content
2016 datacenter_id
= content
['uuid']
2017 where
={'uuid': content
['uuid']}
2018 if "config" in datacenter_descriptor
:
2019 if datacenter_descriptor
['config']!=None:
2021 new_config_dict
= datacenter_descriptor
["config"]
2024 for k
in new_config_dict
:
2025 if new_config_dict
[k
]==None:
2028 config_dict
= yaml
.load(content
["config"])
2029 config_dict
.update(new_config_dict
)
2034 return -HTTP_Bad_Request
, "Bad format at datacenter:config " + str(e
)
2035 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2036 result
, content
= mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2038 return result
, datacenter_id
2039 return 200, datacenter_id
2041 def delete_datacenter(mydb
, datacenter
):
2042 #get nfvo_tenant info
2043 result
,datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2045 return result
, datacenter_dict
2047 result
, datacenter_id
= mydb
.delete_row("datacenters", datacenter_dict
['uuid'], None)
2049 return result
, datacenter_id
2050 return 200, datacenter_dict
['uuid']
2052 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None):
2053 #get datacenter info
2054 if utils
.check_valid_uuid(datacenter
):
2055 result
, vims
= get_vim(mydb
, datacenter_id
=datacenter
)
2057 result
, vims
= get_vim(mydb
, datacenter_name
=datacenter
)
2059 print "nfvo.associate_datacenter_to_tenant() error. Datacenter not found"
2062 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2064 print "nfvo.associate_datacenter_to_tenant() error. Several datacenters found"
2066 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2067 datacenter_id
=vims
.keys()[0]
2068 myvim
=vims
[datacenter_id
]
2069 datacenter_name
=myvim
["name"]
2071 create_vim_tenant
=True if vim_tenant_id
==None and vim_tenant_name
==None else False
2073 #get nfvo_tenant info
2074 result
,tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2076 return result
, tenant_dict
2077 if vim_tenant_name
==None:
2078 vim_tenant_name
=tenant_dict
['name']
2080 #check that this association does not exist before
2081 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2082 result
,content
= mydb
.get_table(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2084 return -HTTP_Conflict
, "datacenter %s and tenant %s are already attached" %(datacenter_id
, tenant_dict
['uuid'])
2086 return result
, content
2088 vim_tenant_id_exist_atdb
=False
2089 if not create_vim_tenant
:
2090 where_
={"datacenter_id": datacenter_id
}
2091 if vim_tenant_id
!=None:
2092 where_
["vim_tenant_id"] = vim_tenant_id
2093 if vim_tenant_name
!=None:
2094 where_
["vim_tenant_name"] = vim_tenant_name
2095 #check if vim_tenant_id is already at database
2096 result
,datacenter_tenants_dict
= mydb
.get_table(FROM
='datacenter_tenants', WHERE
=where_
)
2098 return result
, datacenter_tenants_dict
2100 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2101 vim_tenant_id_exist_atdb
=True
2102 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2104 datacenter_tenants_dict
= {}
2105 #insert at table datacenter_tenants
2106 else: #if vim_tenant_id==None:
2107 #create tenant at VIM if not provided
2108 res
, vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2110 return res
, "Not possible to create vim_tenant in VIM " + vim_tenant_id
2111 datacenter_tenants_dict
= {}
2112 datacenter_tenants_dict
["created"]="true"
2114 #fill datacenter_tenants table
2115 if not vim_tenant_id_exist_atdb
:
2116 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2117 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2118 datacenter_tenants_dict
["user"] = vim_username
2119 datacenter_tenants_dict
["passwd"] = vim_password
2120 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2121 res
,id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, tenant_dict
['uuid'], True, True)
2123 return -HTTP_Bad_Request
, "Not possible to add %s to database datacenter_tenants table %s " %(vim_tenant_id
, id_
)
2124 datacenter_tenants_dict
["uuid"] = id_
2126 #fill tenants_datacenters table
2127 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2128 res
,id_
= mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
, tenant_dict
['uuid'], False, True)
2130 return -HTTP_Bad_Request
, "Not possible to create an entry at database table datacenter_tenants: " + id_
2131 return 200, datacenter_id
2133 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2134 #get datacenter info
2135 if utils
.check_valid_uuid(datacenter
):
2136 result
, vims
= get_vim(mydb
, datacenter_id
=datacenter
)
2138 result
, vims
= get_vim(mydb
, datacenter_name
=datacenter
)
2140 print "nfvo.deassociate_datacenter_to_tenant() error. Datacenter not found"
2143 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2145 print "nfvo.deassociate_datacenter_to_tenant() error. Several datacenters found"
2146 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2147 datacenter_id
=vims
.keys()[0]
2148 myvim
=vims
[datacenter_id
]
2150 #get nfvo_tenant info
2151 if not tenant_id
or tenant_id
=="any":
2154 result
,tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2156 return result
, tenant_dict
2157 tenant_uuid
= tenant_dict
['uuid']
2159 #check that this association exist before
2160 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2162 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2163 result
,tenant_datacenter_list
= mydb
.get_table(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2164 if result
==0 and tenant_uuid
:
2165 return -HTTP_Not_Found
, "datacenter %s and tenant %s are not attached" %(datacenter_id
, tenant_dict
['uuid'])
2167 return result
, tenant_datacenter_list
2169 #delete this association
2170 result
,data
= mydb
.delete_row_by_dict(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2174 #get vim_tenant info and deletes
2176 for tenant_datacenter_item
in tenant_datacenter_list
:
2177 result
,vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2179 #try to delete vim:tenant
2180 result
,data
= mydb
.delete_row('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'], tenant_uuid
)
2182 pass #the error will be caused because dependencies, vim_tenant can not be deleted
2183 elif vim_tenant_dict
['created']=='true':
2184 #delete tenant at VIM if created by NFVO
2185 res
, vim_tenant_id
= myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2187 warning
= " Not possible to delete vim_tenant id %s name %s from VIM: %s " % (vim_tenant_dict
['vim_tenant_id'], vim_tenant_dict
['vim_tenant_name'], vim_tenant_id
)
2190 return 200, "datacenter %s detached.%s" %(datacenter_id
, warning
)
2192 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2194 #get datacenter info
2195 if utils
.check_valid_uuid(datacenter
):
2196 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2198 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2200 print "nfvo.datacenter_action() error. Datacenter not found"
2203 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2205 print "nfvo.datacenter_action() error. Several datacenters found"
2206 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2207 datacenter_id
=vims
.keys()[0]
2208 myvim
=vims
[datacenter_id
]
2210 if 'net-update' in action_dict
:
2211 result
, content
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2214 print " Not possible to get_network_list from VIM: %s " % (content
)
2215 return -HTTP_Internal_Server_Error
, content
2216 #update nets Change from VIM format to NFVO format
2219 net_nfvo
={'datacenter_id': datacenter_id
}
2220 net_nfvo
['name'] = net
['name']
2221 #net_nfvo['description']= net['name']
2222 net_nfvo
['vim_net_id'] = net
['id']
2223 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2224 net_nfvo
['shared'] = net
['shared']
2225 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2226 net_list
.append(net_nfvo
)
2227 result
, content
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2229 return -HTTP_Internal_Server_Error
, content
2230 print "Inserted %d nets, deleted %d old nets" % (result
, content
)
2233 elif 'net-edit' in action_dict
:
2234 net
= action_dict
['net-edit'].pop('net')
2235 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2236 result
, content
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2237 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2238 return result
, content
2239 elif 'net-delete' in action_dict
:
2240 net
= action_dict
['net-deelte'].get('net')
2241 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2242 result
, content
= mydb
.delete_row_by_dict(FROM
='datacenter_nets',
2243 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2244 return result
, content
2247 return -HTTP_Bad_Request
, "Unknown action " + str(action_dict
)
2249 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2250 #get datacenter info
2251 if utils
.check_valid_uuid(datacenter
):
2252 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2254 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2256 print "nfvo.datacenter_action() error. Datacenter not found"
2259 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2261 print "nfvo.datacenter_action() error. Several datacenters found"
2262 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2263 datacenter_id
=vims
.keys()[0]
2265 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2266 result
, content
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2267 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2268 return result
, content
2270 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2271 #get datacenter info
2272 if utils
.check_valid_uuid(datacenter
):
2273 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2275 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2277 print "nfvo.datacenter_new_netmap() error. Datacenter not found"
2280 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2282 print "nfvo.datacenter_new_netmap() error. Several datacenters found"
2283 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2284 datacenter_id
=vims
.keys()[0]
2285 myvim
=vims
[datacenter_id
]
2288 action_dict
= action_dict
["netmap"]
2289 if 'vim_id' in action_dict
:
2290 filter_dict
["id"] = action_dict
['vim_id']
2291 if 'vim_name' in action_dict
:
2292 filter_dict
["name"] = action_dict
['vim_name']
2294 filter_dict
["shared"] = True
2296 result
, content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2297 print result
, content
2299 print " Not possible to get_network_list from VIM: %s " % (content
)
2300 return -HTTP_Internal_Server_Error
, content
2301 elif len(content
)>1 and action_dict
:
2302 return -HTTP_Conflict
, "more than two networks found, specify with vim_id"
2303 elif len(content
)==0: # and action_dict:
2304 return -HTTP_Not_Found
, "Not found a network at VIM with " + str(filter_dict
)
2307 net_nfvo
={'datacenter_id': datacenter_id
}
2308 if action_dict
and "name" in action_dict
:
2309 net_nfvo
['name'] = action_dict
['name']
2311 net_nfvo
['name'] = net
['name']
2312 #net_nfvo['description']= net['name']
2313 net_nfvo
['vim_net_id'] = net
['id']
2314 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2315 net_nfvo
['shared'] = net
['shared']
2316 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2317 result
, content
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2318 if action_dict
and result
< 0 :
2319 return result
, content
2321 net_nfvo
["status"] = "FAIL: " + content
2323 net_nfvo
["status"] = "OK"
2324 net_nfvo
["uuid"] = content
2325 net_list
.append(net_nfvo
)
2326 return 200, net_list
2328 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2329 #get datacenter info
2330 if utils
.check_valid_uuid(datacenter
):
2331 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2333 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2335 print "nfvo.datacenter_action() error. Datacenter not found"
2338 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2340 print "nfvo.datacenter_action() error. Several datacenters found"
2341 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2342 datacenter_id
=vims
.keys()[0]
2343 myvim
=vims
[datacenter_id
]
2346 if utils
.check_valid_uuid(name
):
2347 filter_dict
["id"] = name
2349 filter_dict
["name"] = name
2350 if item
=="networks":
2351 #filter_dict['tenant_id'] = myvim['tenant_id']
2352 result
, content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2353 elif item
=="tenants":
2354 result
, content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2356 return -HTTP_Method_Not_Allowed
, item
+ "?"
2358 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, content
)
2359 return -HTTP_Internal_Server_Error
, content
2360 print "vim_action response ", content
#update nets Change from VIM format to NFVO format
2361 if name
and len(content
)==1:
2362 return 200, {item
[:-1]: content
[0]}
2363 elif name
and len(content
)==0:
2364 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())))
2366 return 200, {item
: content
}
2368 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
2369 #get datacenter info
2370 if tenant_id
== "any":
2373 if af
.check_valid_uuid(datacenter
):
2374 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2376 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2378 print "nfvo.datacenter_action() error. Datacenter not found"
2381 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2383 print "nfvo.datacenter_action() error. Several datacenters found"
2384 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2385 datacenter_id
=vims
.keys()[0]
2386 myvim
=vims
[datacenter_id
]
2388 result
, content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2391 return result
, content
2392 items
= content
.values()[0]
2393 if type(items
)==list and len(items
)==0:
2394 return -HTTP_Not_Found
, "Not found " + item
2395 elif type(items
)==list and len(items
)>1:
2396 return -HTTP_Not_Found
, "Found more than one %s with this name. Use uuid." % item
2397 else: # it is a dict
2398 item_id
= items
["id"]
2399 item_name
= str(items
.get("name"))
2401 if item
=="networks":
2402 result
, content
= myvim
.delete_tenant_network(item_id
)
2403 elif item
=="tenants":
2404 result
, content
= myvim
.delete_tenant(item_id
)
2406 return -HTTP_Method_Not_Allowed
, item
+ "?"
2408 print "vim_action Not possible to delete %s %s from VIM: %s " % (item
, name
, content
)
2409 return result
, content
2410 return 200, "%s %s %s deleted" %( item
[:-1], item_id
,item_name
)
2412 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2413 #get datacenter info
2414 print "vim_action_create descriptor", descriptor
2415 if tenant_id
== "any":
2418 if utils
.check_valid_uuid(datacenter
):
2419 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2421 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2423 print "nfvo.datacenter_action() error. Datacenter not found"
2426 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2428 print "nfvo.datacenter_action() error. Several datacenters found"
2429 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2430 datacenter_id
=vims
.keys()[0]
2431 myvim
=vims
[datacenter_id
]
2433 if item
=="networks":
2434 net
= descriptor
["network"]
2435 net_name
= net
.pop("name")
2436 net_type
= net
.pop("type", "bridge")
2437 net_public
=net
.pop("shared", False)
2438 result
, content
= myvim
.new_tenant_network(net_name
, net_type
, net_public
, **net
)
2439 elif item
=="tenants":
2440 tenant
= descriptor
["tenant"]
2441 result
, content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2443 return -HTTP_Method_Not_Allowed
, item
+ "?"
2445 print "vim_action Not possible to create %s at VIM: %s " % (item
, content
)
2446 return result
, content
2447 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)