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$"
33 from utils
import auxiliary_functions
as af
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"]
143 tenant
=vim
.get('vim_tenant_id')
145 tenant
=vim
.get('vim_tenant_name')
147 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
148 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
149 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
151 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
152 user
=vim
.get('user'), passwd
=vim
.get('passwd'),
155 except Exception as e
:
156 return -HTTP_Internal_Server_Error
, "Error at VIM %s; %s: %s" % ( vim
["type"], type(e
).__name
__, str(e
))
157 return len(vim_dict
), vim_dict
159 def rollback(mydb
, vims
, rollback_list
):
161 #delete things by reverse order
162 for i
in range(len(rollback_list
)-1, -1, -1):
163 item
= rollback_list
[i
]
164 if item
["where"]=="vim":
165 if item
["vim_id"] not in vims
:
167 vim
=vims
[ item
["vim_id"] ]
168 if item
["what"]=="image":
169 result
, message
= vim
.delete_tenant_image(item
["uuid"])
171 print "Error in rollback. Not possible to delete VIM image '%s'. Message: %s" % (item
["uuid"],message
)
172 undeleted_items
.append("image %s from VIM %s" % (item
["uuid"],vim
["name"]))
174 result
, message
= mydb
.delete_row_by_dict(FROM
="datacenters_images", WEHRE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
176 print "Error in rollback. Not possible to delete image '%s' from DB.dacenters_images. Message: %s" % (item
["uuid"],message
)
177 elif item
["what"]=="flavor":
178 result
, message
= vim
.delete_tenant_flavor(item
["uuid"])
180 print "Error in rollback. Not possible to delete VIM flavor '%s'. Message: %s" % (item
["uuid"],message
)
181 undeleted_items
.append("flavor %s from VIM %s" % (item
["uuid"],vim
["name"]))
183 result
, message
= mydb
.delete_row_by_dict(FROM
="datacenters_flavos", WEHRE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
185 print "Error in rollback. Not possible to delete flavor '%s' from DB.dacenters_flavors. Message: %s" % (item
["uuid"],message
)
186 elif item
["what"]=="network":
187 result
, message
= vim
.delete_tenant_network(item
["uuid"])
189 print "Error in rollback. Not possible to delete VIM network '%s'. Message: %s" % (item
["uuid"],message
)
190 undeleted_items
.append("network %s from VIM %s" % (item
["uuid"],vim
["name"]))
191 elif item
["what"]=="vm":
192 result
, message
= vim
.delete_tenant_vminstance(item
["uuid"])
194 print "Error in rollback. Not possible to delete VIM VM '%s'. Message: %s" % (item
["uuid"],message
)
195 undeleted_items
.append("VM %s from VIM %s" % (item
["uuid"],vim
["name"]))
197 if item
["what"]=="image":
198 result
, message
= mydb
.delete_row_by_dict(FROM
="images", WEHRE
={"uuid": item
["uuid"]})
200 print "Error in rollback. Not possible to delete image '%s' from DB.images. Message: %s" % (item
["uuid"],message
)
201 undeleted_items
.append("image %s" % (item
["uuid"]))
202 elif item
["what"]=="flavor":
203 result
, message
= mydb
.delete_row_by_dict(FROM
="flavors", WEHRE
={"uuid": item
["uuid"]})
205 print "Error in rollback. Not possible to delete flavor '%s' from DB.flavors. Message: %s" % (item
["uuid"],message
)
206 undeleted_items
.append("flavor %s" % (item
["uuid"]))
207 if len(undeleted_items
)==0:
208 return True," Rollback successful."
210 return False," Rollback fails to delete: " + str(undeleted_items
)
212 def check_vnf_descriptor(vnf_descriptor
):
214 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
216 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
218 #dataplane interfaces
219 for numa
in vnfc
.get("numas",() ):
220 for interface
in numa
.get("interfaces",()):
221 if interface
["name"] in name_list
:
222 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"])
223 name_list
.append( interface
["name"] )
225 for interface
in vnfc
.get("bridge-ifaces",() ):
226 if interface
["name"] in name_list
:
227 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"])
228 name_list
.append( interface
["name"] )
229 vnfc_interfaces
[ vnfc
["name"] ] = name_list
231 #check if the info in external_connections matches with the one in the vnfcs
233 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
234 if external_connection
["name"] in name_list
:
235 return -HTTP_Bad_Request
, "Error at vnf:external-connections:name, value '%s' already used as an external-connection" %(external_connection
["name"])
236 name_list
.append(external_connection
["name"])
237 if external_connection
["VNFC"] not in vnfc_interfaces
:
238 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"])
239 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
240 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"])
242 #check if the info in internal_connections matches with the one in the vnfcs
244 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
245 if internal_connection
["name"] in name_list
:
246 return -HTTP_Bad_Request
, "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection" %(internal_connection
["name"])
247 name_list
.append(internal_connection
["name"])
248 #We should check that internal-connections of type "ptp" have only 2 elements
249 if len(internal_connection
["elements"])>2 and internal_connection
["type"] == "ptp":
250 return -HTTP_Bad_Request
, "Error at vnf:internal-connections[name:'%s']:elements, size must be 2 for a type:'ptp'" %(internal_connection
["name"])
251 for port
in internal_connection
["elements"]:
252 if port
["VNFC"] not in vnfc_interfaces
:
253 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"])
254 if port
["local_iface_name"] not in vnfc_interfaces
[ port
["VNFC"] ]:
255 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"])
260 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
262 if only_create_at_vim
:
263 image_mano_id
= image_dict
['uuid']
265 res
,content
= mydb
.get_table(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
267 image_mano_id
= content
[0]['uuid']
272 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
273 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None)
275 res
,content
= mydb
.new_row('images', temp_image_dict
, tenant_id
=None, add_uuid
=True)
277 image_mano_id
= content
278 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
280 return res
if res
<0 else -1, content
281 #create image at every vim
282 for vim_id
,vim
in vims
.iteritems():
283 image_created
="false"
285 res_db
,image_db
= mydb
.get_table(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
287 return res_db
, image_db
288 #look at VIM if this image exist
289 res_vim
, image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
291 print "Error contacting VIM to know if the image %s existed previously." %image
_vim
_id
294 #Create the image in VIM
295 result
, image_vim_id
= vim
.new_tenant_image(image_dict
)
297 print "Error creating image at VIM: %s." %image
_vim
_id
299 return result
, image_vim_id
302 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
305 #if reach here the image has been create or exist
307 #add new vim_id at datacenters_images
308 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
309 elif image_db
[0]["vim_id"]!=image_vim_id
:
310 #modify existing vim_id at datacenters_images
311 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
313 return 1, image_vim_id
if only_create_at_vim
else image_mano_id
315 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
316 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
317 'ram':flavor_dict
.get('ram'),
318 'vcpus':flavor_dict
.get('vcpus'),
320 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
321 del flavor_dict
['extended']
322 if 'extended' in flavor_dict
:
323 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
325 #look if flavor exist
326 if only_create_at_vim
:
327 flavor_mano_id
= flavor_dict
['uuid']
329 res
,content
= mydb
.get_table(FROM
="flavors", WHERE
=temp_flavor_dict
)
331 flavor_mano_id
= content
[0]['uuid']
336 #create one by one the images of aditional disks
337 dev_image_list
=[] #list of images
338 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
340 for device
in flavor_dict
['extended'].get('devices',[]):
341 if "image" not in device
:
343 image_dict
={'location':device
['image'], 'name':flavor_dict
['name']+str(dev_nb
)+"-img", 'description':flavor_dict
.get('description')}
344 image_metadata_dict
= device
.get('image metadata', None)
345 image_metadata_str
= None
346 if image_metadata_dict
!= None:
347 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
348 image_dict
['metadata']=image_metadata_str
349 res
, image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
351 return res
, image_id
+ rollback(mydb
, vims
, rollback_list
)[1]
352 print "Additional disk image id for VNFC %s: %s" % (flavor_dict
['name']+str(dev_nb
)+"-img", image_id
)
353 dev_image_list
.append(image_id
)
355 temp_flavor_dict
['name'] = flavor_dict
['name']
356 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
357 res
,content
= mydb
.new_row('flavors', temp_flavor_dict
, tenant_id
=None, add_uuid
=True)
359 flavor_mano_id
= content
360 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
362 return res
if res
<0 else -1, content
363 #create flavor at every vim
364 if 'uuid' in flavor_dict
:
365 del flavor_dict
['uuid']
367 for vim_id
,vim
in vims
.items():
368 flavor_created
="false"
370 res_db
,flavor_db
= mydb
.get_table(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
372 return res_db
, flavor_db
373 #look at VIM if this flavor exist SKIPPED
374 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
376 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
380 #Create the flavor in VIM
381 #Translate images at devices from MANO id to VIM id
383 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
384 #make a copy of original devices
386 for device
in flavor_dict
["extended"].get("devices",[]):
389 devices_original
.append(dev
)
390 if 'image' in device
:
392 if 'image metadata' in device
:
393 del device
['image metadata']
395 for index
in range(0,len(devices_original
)) :
396 device
=devices_original
[index
]
397 if "image" not in device
:
399 image_dict
={'location':device
['image'], 'name':flavor_dict
['name']+str(dev_nb
)+"-img", 'description':flavor_dict
.get('description')}
400 image_metadata_dict
= device
.get('image metadata', None)
401 image_metadata_str
= None
402 if image_metadata_dict
!= None:
403 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
404 image_dict
['metadata']=image_metadata_str
405 r
,image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False)
407 print "Error creating device image for flavor: %s." %image
_mano
_id
408 error_text
= image_mano_id
411 image_dict
["uuid"]=image_mano_id
412 r
,image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True)
414 print "Error creating device image for flavor at VIM: %s." %image
_vim
_id
415 error_text
= image_vim_id
418 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
425 #check that this vim_id exist in VIM, if not create
426 flavor_vim_id
=flavor_db
[0]["vim_id"]
427 result
, _
= vim
.get_tenant_flavor(flavor_vim_id
)
428 if result
>=0: #flavor exist
430 #create flavor at vim
431 print "nfvo.create_or_use_flavor() adding flavor to VIM %s" % vim
["name"]
432 result
, flavor_vim_id
= vim
.new_tenant_flavor(flavor_dict
)
435 print "Error creating flavor at VIM %s: %s." %(vim
["name"], flavor_vim_id
)
437 return result
, flavor_vim_id
440 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
441 flavor_created
="true"
443 #if reach here the flavor has been create or exist
445 #add new vim_id at datacenters_flavors
446 mydb
.new_row('datacenters_flavors', {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
, 'created':flavor_created
})
447 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
448 #modify existing vim_id at datacenters_flavors
449 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
451 return 1, flavor_vim_id
if only_create_at_vim
else flavor_mano_id
453 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
456 # Step 1. Check the VNF descriptor
457 result
, message
= check_vnf_descriptor(vnf_descriptor
)
459 print "new_vnf error: %s" %message
460 return result
, message
462 # Step 2. Check tenant exist
463 if tenant_id
!= "any":
464 if not check_tenant(mydb
, tenant_id
):
465 print 'nfvo.new_vnf() tenant %s not found' % tenant_id
466 return -HTTP_Not_Found
, 'Tenant %s not found' % tenant_id
467 if "tenant_id" in vnf_descriptor
["vnf"]:
468 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
469 print "nfvo.new_vnf() tenant '%s' not found" % tenant_id
470 return -HTTP_Unauthorized
, "VNF can not have a different tenant owner '%s', must be '%s'" %(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
)
472 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
473 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
474 result
, vims
= get_vim(mydb
, tenant_id
)
476 print "nfvo.new_vnf() error. Datacenter not found"
481 # Step 4. Review the descriptor and add missing fields
482 #print vnf_descriptor
483 print "Refactoring VNF descriptor with fields: description, public (default: true)"
484 vnf_name
= vnf_descriptor
['vnf']['name']
485 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
486 if "physical" in vnf_descriptor
['vnf']:
487 del vnf_descriptor
['vnf']['physical']
488 #print vnf_descriptor
489 # Step 5. Check internal connections
490 # TODO: to be moved to step 1????
491 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
492 for ic
in internal_connections
:
493 if len(ic
['elements'])>2 and ic
['type']=='ptp':
494 return -HTTP_Bad_Request
, "Mismatch 'type':'ptp' with %d elements at 'vnf':'internal-conections'['name':'%s']. Change 'type' to 'data'" %(len(ic
), ic
['name'])
495 elif len(ic
['elements'])==2 and ic
['type']=='data':
496 return -HTTP_Bad_Request
, "Mismatch 'type':'data' with 2 elements at 'vnf':'internal-conections'['name':'%s']. Change 'type' to 'ptp'" %(ic
['name'])
498 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
499 print 'BEGIN creation of VNF "%s"' % vnf_name
500 print "VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC']))
502 #For each VNFC, we add it to the VNFCDict and we create a flavor.
503 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
504 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
507 print "Creating additional disk images and new flavors in the VIM for each VNFC"
508 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
510 VNFCitem
["name"] = vnfc
['name']
511 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
513 print "Flavor name: %s. Description: %s" % (VNFCitem
["name"]+"-flv", VNFCitem
["description"])
516 myflavorDict
["name"] = vnfc
['name']+"-flv"
517 myflavorDict
["description"] = VNFCitem
["description"]
518 myflavorDict
["ram"] = vnfc
.get("ram", 0)
519 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
520 myflavorDict
["disk"] = vnfc
.get("disk", 1)
521 myflavorDict
["extended"] = {}
523 devices
= vnfc
.get("devices")
525 myflavorDict
["extended"]["devices"] = devices
528 # 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
529 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
531 # Previous code has been commented
532 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
533 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
534 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
535 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
537 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
539 # print "Error creating flavor: unknown processor model. Rollback successful."
540 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
542 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
543 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
545 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
546 myflavorDict
['extended']['numas'] = vnfc
['numas']
550 # Step 6.2 New flavors are created in the VIM
551 res
, flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
553 return res
, flavor_id
+ rollback(mydb
, vims
, rollback_list
)[1]
555 print "Flavor id for VNFC %s: %s" % (vnfc
['name'],flavor_id
)
556 VNFCitem
["flavor_id"] = flavor_id
557 VNFCDict
[vnfc
['name']] = VNFCitem
559 print "Creating new images in the VIM for each VNFC"
560 # Step 6.3 New images are created in the VIM
561 #For each VNFC, we must create the appropriate image.
562 #This "for" loop might be integrated with the previous one
563 #In case this integration is made, the VNFCDict might become a VNFClist.
564 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
565 print "Image name: %s. Description: %s" % (vnfc
['name']+"-img", VNFCDict
[vnfc
['name']]['description'])
566 image_dict
={'location':vnfc
['VNFC image'], 'name':vnfc
['name']+"-img", 'description':VNFCDict
[vnfc
['name']]['description']}
567 image_metadata_dict
= vnfc
.get('image metadata', None)
568 image_metadata_str
= None
569 if image_metadata_dict
is not None:
570 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
571 image_dict
['metadata']=image_metadata_str
572 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
573 res
, image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
575 return res
, image_id
+ rollback(mydb
, vims
, rollback_list
)[1]
576 print "Image id for VNFC %s: %s" % (vnfc
['name'],image_id
)
577 VNFCDict
[vnfc
['name']]["image_id"] = image_id
578 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
['VNFC image']
580 except KeyError as e
:
581 print "Error while creating a VNF. KeyError: " + str(e
)
582 _
, message
= rollback(mydb
, vims
, rollback_list
)
583 return -HTTP_Internal_Server_Error
, "Error while creating a VNF. KeyError " + str(e
) + "." + message
585 # Step 7. Storing the VNF descriptor in the repository
586 if "descriptor" not in vnf_descriptor
["vnf"]:
587 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
589 # Step 8. Adding the VNF to the NFVO DB
591 result
, vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
592 except KeyError as e
:
593 print "Error while creating a VNF. KeyError: " + str(e
)
594 _
, message
= rollback(mydb
, vims
, rollback_list
)
595 return -HTTP_Internal_Server_Error
, "Error while creating a VNF. KeyError " + str(e
) + "." + message
598 _
, message
= rollback(mydb
, vims
, rollback_list
)
599 return result
, vnf_id
+ "." + message
603 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
604 #check valid tenant_id
605 if tenant_id
!= "any" and not check_tenant(mydb
, tenant_id
):
606 print 'nfvo.get_vnf_id() tenant %s not found' % tenant_id
607 return -HTTP_Not_Found
, "Tenant '%s' not found" % tenant_id
610 if tenant_id
!= "any":
611 where_or
["tenant_id"] = tenant_id
612 where_or
["public"] = True
613 result
, content
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
615 print "nfvo.get_vnf_id() error %d %s" % (result
, content
)
616 return (result
, content
)
619 vnf_id
=content
["uuid"]
620 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
621 filtered_content
= dict( (k
,v
) for k
,v
in content
.iteritems() if k
in filter_keys
)
622 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
623 data
={'vnf' : filtered_content
}
625 result
,content
= mydb
.get_table(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
626 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description'),
627 WHERE
={'vnfs.uuid': vnf_id
} )
629 print "nfvo.get_vnf_id error %d %s" % (result
, content
)
630 return (result
, content
)
632 print "nfvo.get_vnf_id vnf '%s' not found" % vnf_id
633 return (-HTTP_Not_Found
, "vnf %s not found" % vnf_id
)
635 data
['vnf']['VNFC'] = content
637 result
,content
= mydb
.get_table(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
638 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
639 WHERE
={'vnfs.uuid': vnf_id
} )
641 print "nfvo.get_vnf_id error %d %s" % (result
, content
)
642 return (result
, content
)
645 data
['vnf']['nets'] = []
647 data
['vnf']['nets'] = content
649 result
,content
= mydb
.get_table(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
650 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
651 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
652 WHERE
={'vnfs.uuid': vnf_id
},
653 WHERE_NOT
={'interfaces.external_name': None} )
656 print "nfvo.get_vnf_id error %d %s" % (result
, content
)
657 return (result
, content
)
660 data
['vnf']['external-connections'] = []
662 data
['vnf']['external-connections'] = content
666 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
668 if tenant_id
!= "any":
669 if not check_tenant(mydb
, tenant_id
):
670 print 'nfvo.delete_vnf() tenant %s not found' % tenant_id
671 return -HTTP_Not_Found
, 'Tenant %s not found' % tenant_id
672 # Get the URL of the VIM from the nfvo_tenant and the datacenter
673 result
, vims
= get_vim(mydb
, tenant_id
)
675 print "nfvo.delete_vnf() error. Datacenter not found"
680 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
682 if tenant_id
!= "any":
683 where_or
["tenant_id"] = tenant_id
684 where_or
["public"] = True
685 result
, content
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
687 return result
, content
688 vnf_id
= content
["uuid"]
690 # "Getting the list of flavors and tenants of the VNF"
691 result
,flavorList
= get_flavorlist(mydb
, vnf_id
)
695 print "delete_vnf error. No flavors found for the VNF id '%s'" % vnf_id
697 result
,imageList
= get_imagelist(mydb
, vnf_id
)
698 print "imageList", imageList
702 print "delete_vnf error. No images found for the VNF id '%s'" % vnf_id
704 result
, content
= mydb
.delete_row('vnfs', vnf_id
, tenant_id
)
706 return -HTTP_Not_Found
, content
710 print "delete_vnf error",result
, content
711 return result
, content
714 for flavor
in flavorList
:
715 #check if flavor is used by other vnf
716 r
,c
= mydb
.get_table(FROM
='vms', WHERE
={'flavor_id':flavor
} )
718 print 'delete_vnf_error. Not possible to delete VIM flavor "%s". %s' % (flavor
,c
)
719 undeletedItems
.append("flavor "+ flavor
["flavor_id"])
721 print 'Flavor %s not deleted because it is being used by another VNF %s' %(flavor
,str(c
))
723 #flavor not used, must be deleted
725 r
,c
= mydb
.get_table(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
728 if flavor_vim
["datacenter_id"] not in vims
:
730 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
732 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
733 result
, message
= myvim
.delete_tenant_flavor(flavor_vim
["vim_id"])
735 print 'delete_vnf_error. Not possible to delete VIM flavor "%s". Message: %s' % (flavor
,message
)
736 if result
!= -HTTP_Not_Found
:
737 undeletedItems
.append("flavor %s from VIM %s" % (flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
738 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
739 result
, content
= mydb
.delete_row('flavors', flavor
)
741 undeletedItems
.append("flavor %s" % flavor
)
743 for image
in imageList
:
744 #check if image is used by other vnf
745 r
,c
= mydb
.get_table(FROM
='vms', WHERE
={'image_id':image
} )
747 print 'delete_vnf_error. Not possible to delete VIM image "%s". %s' % (image
,c
)
748 undeletedItems
.append("image "+ image
["image_id"])
750 print 'Image %s not deleted because it is being used by another VNF %s' %(image
,str(c
))
752 #image not used, must be deleted
754 r
,c
= mydb
.get_table(FROM
='datacenters_images', WHERE
={'image_id':image
})
757 if image_vim
["datacenter_id"] not in vims
:
759 if image_vim
['created']=='false': #skip this image because not created by openmano
761 myvim
=vims
[ image_vim
["datacenter_id"] ]
762 result
, message
= myvim
.delete_tenant_image(image_vim
["vim_id"])
764 print 'delete_vnf_error. Not possible to delete VIM image "%s". Message: %s' % (image
,message
)
765 if result
!= -HTTP_Not_Found
:
766 undeletedItems
.append("image %s from VIM %s" % (image_vim
["vim_id"], image_vim
["datacenter_id"] ))
767 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
768 result
, content
= mydb
.delete_row('images', image
)
770 undeletedItems
.append("image %s" % image
)
773 return 200, "delete_vnf error. Undeleted: %s" %(undeletedItems)
777 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
778 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
782 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
783 myvim
= vims
.values()[0]
784 result
,servers
= myvim
.get_hosts_info()
786 return result
, servers
787 topology
= {'name':myvim
['name'] , 'servers': servers
}
788 return result
, topology
790 def get_hosts(mydb
, nfvo_tenant_id
):
791 result
, vims
= get_vim(mydb
, nfvo_tenant_id
)
795 return -HTTP_Not_Found
, "No datacenter found"
796 myvim
= vims
.values()[0]
797 result
,hosts
= myvim
.get_hosts()
800 print '==================='
801 print 'hosts '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False)
803 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
805 server
={'name':host
['name'], 'vms':[]}
806 for vm
in host
['instances']:
807 #get internal name and model
808 r
,c
= mydb
.get_table(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
809 WHERE
={'vim_vm_id':vm
['id']} )
811 print "nfvo.get_hosts virtual machine at VIM (%s) not found at tidnfvo" % vm
['id']
814 print "nfvo.get_hosts virtual machine at VIM (%s) error %d %s" % (vm
['id'], r
, c
)
816 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
817 datacenter
['Datacenters'][0]['servers'].append(server
)
818 #return -400, "en construccion"
820 #print 'datacenters '+ json.dumps(datacenter, indent=4)
821 return result
, datacenter
823 def new_scenario(mydb
, tenant_id
, topo
):
825 # result, vims = get_vim(mydb, tenant_id)
827 # return result, vims
829 if tenant_id
!= "any":
830 if not check_tenant(mydb
, tenant_id
):
831 print 'nfvo.new_scenario() tenant %s not found' % tenant_id
832 return -HTTP_Not_Found
, 'Tenant %s not found' % tenant_id
833 if "tenant_id" in topo
:
834 if topo
["tenant_id"] != tenant_id
:
835 print "nfvo.new_scenario() tenant '%s' not found" % tenant_id
836 return -HTTP_Unauthorized
, "VNF can not have a different tenant owner '%s', must be '%s'" %(topo
["tenant_id"], tenant_id
)
840 #1.1: get VNFs and external_networks (other_nets).
842 other_nets
={} #external_networks, bridge_networks and data_networkds
843 nodes
= topo
['topology']['nodes']
844 for k
in nodes
.keys():
845 if nodes
[k
]['type'] == 'VNF':
847 vnfs
[k
]['ifaces'] = {}
848 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
849 other_nets
[k
] = nodes
[k
]
850 other_nets
[k
]['external']=True
851 elif nodes
[k
]['type'] == 'network':
852 other_nets
[k
] = nodes
[k
]
853 other_nets
[k
]['external']=False
856 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
857 for name
,vnf
in vnfs
.items():
860 error_pos
= "'topology':'nodes':'" + name
+ "'"
862 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
863 WHERE_
['uuid'] = vnf
['vnf_id']
864 if 'VNF model' in vnf
:
865 error_text
+= " 'VNF model' " + vnf
['VNF model']
866 WHERE_
['name'] = vnf
['VNF model']
868 return -HTTP_Bad_Request
, "needed a 'vnf_id' or 'VNF model' at " + error_pos
869 r
,vnf_db
= mydb
.get_table(SELECT
=('uuid','name','description'), FROM
='vnfs', WHERE
=WHERE_
)
871 print "nfvo.new_scenario Error getting vnfs",r
,vnf_db
873 print "nfvo.new_scenario Error" + error_text
+ " is not present at database"
874 return -HTTP_Bad_Request
, "unknown" + error_text
+ " at " + error_pos
876 print "nfvo.new_scenario Error more than one" + error_text
+ " are present at database"
877 return -HTTP_Bad_Request
, "more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'"
878 vnf
['uuid']=vnf_db
[0]['uuid']
879 vnf
['description']=vnf_db
[0]['description']
880 #get external interfaces
881 r
,ext_ifaces
= mydb
.get_table(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
882 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
883 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
885 print "nfvo.new_scenario Error getting external interfaces of vnfs",r
,ext_ifaces
886 return -HTTP_Internal_Server_Error
, "Error getting external interfaces of vnfs: " + ext_ifaces
887 for ext_iface
in ext_ifaces
:
888 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
890 #1.4 get list of connections
891 conections
= topo
['topology']['connections']
893 for k
in conections
.keys():
894 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
895 ifaces_list
= conections
[k
]['nodes'].items()
896 elif type(conections
[k
]['nodes'])==list: #list with dictionary
898 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
899 for k2
in conection_pair_list
:
902 con_type
= conections
[k
].get("type", "link")
903 if con_type
!= "link":
905 return -HTTP_Bad_Request
, "format error. Reapeted network name at 'topology':'connections':'%s'" % (str(k
))
906 other_nets
[k
] = {'external': False}
907 if conections
[k
].get("graph"):
908 other_nets
[k
]["graph"] = conections
[k
]["graph"]
909 ifaces_list
.append( (k
, None) )
912 if con_type
== "external_network":
913 other_nets
[k
]['external'] = True
914 if conections
[k
].get("model"):
915 other_nets
[k
]["model"] = conections
[k
]["model"]
917 other_nets
[k
]["model"] = k
918 if con_type
== "dataplane_net" or con_type
== "bridge_net":
919 other_nets
[k
]["model"] = con_type
922 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)
923 #print set(ifaces_list)
924 #check valid VNF and iface names
925 for iface
in ifaces_list
:
926 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
927 return -HTTP_Bad_Request
, "format error. Invalid VNF name at 'topology':'connections':'%s':'nodes':'%s'" % (str(k
), iface
[0])
928 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
929 return -HTTP_Bad_Request
, "format error. Invalid interface name at 'topology':'connections':'%s':'nodes':'%s':'%s'" % (str(k
), iface
[0], iface
[1])
931 #1.5 unify connections from the pair list to a consolidated list
933 while index
< len(conections_list
):
935 while index2
< len(conections_list
):
936 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
937 conections_list
[index
] |
= conections_list
[index2
]
938 del conections_list
[index2
]
941 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
943 #for k in conections_list:
948 #1.6 Delete non external nets
949 # for k in other_nets.keys():
950 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
951 # for con in conections_list:
953 # for index in range(0,len(con)):
954 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
955 # for index in delete_indexes:
958 #1.7: Check external_ports are present at database table datacenter_nets
959 for k
,net
in other_nets
.items():
960 error_pos
= "'topology':'nodes':'" + k
+ "'"
961 if net
['external']==False:
962 if 'name' not in net
:
964 if 'model' not in net
:
965 return -HTTP_Bad_Request
, "needed a 'model' at " + error_pos
966 if net
['model']=='bridge_net':
967 net
['type']='bridge';
968 elif net
['model']=='dataplane_net':
971 return -HTTP_Bad_Request
, "unknown 'model' '"+ net
['model'] +"' at " + error_pos
973 #IF we do not want to check that external network exist at datacenter
978 # if 'net_id' in net:
979 # error_text += " 'net_id' " + net['net_id']
980 # WHERE_['uuid'] = net['net_id']
982 # error_text += " 'model' " + net['model']
983 # WHERE_['name'] = net['model']
984 # if len(WHERE_) == 0:
985 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
986 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
987 # FROM='datacenter_nets', WHERE=WHERE_ )
989 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
991 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
992 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
994 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
995 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
996 # other_nets[k].update(net_db[0])
999 net_nb
=0 #Number of nets
1000 for con
in conections_list
:
1001 #check if this is connected to a external net
1005 for index
in range(0,len(con
)):
1006 #check if this is connected to a external net
1007 for net_key
in other_nets
.keys():
1008 if con
[index
][0]==net_key
:
1009 if other_net_index
>=0:
1010 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1011 print "nfvo.new_scenario " + error_text
1012 return -HTTP_Bad_Request
, error_text
1014 other_net_index
= index
1015 net_target
= net_key
1017 #print "other_net_index", other_net_index
1019 if other_net_index
>=0:
1020 del con
[other_net_index
]
1021 #IF we do not want to check that external network exist at datacenter
1022 if other_nets
[net_target
]['external'] :
1023 if "name" not in other_nets
[net_target
]:
1024 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1025 if other_nets
[net_target
]["type"] == "external_network":
1026 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1027 other_nets
[net_target
]["type"] = "data"
1029 other_nets
[net_target
]["type"] = "bridge"
1031 # if other_nets[net_target]['external'] :
1032 # 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
1033 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1034 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1035 # print "nfvo.new_scenario " + error_text
1036 # return -HTTP_Bad_Request, error_text
1039 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1042 net_type_bridge
=False
1044 net_target
= "__-__net"+str(net_nb
)
1045 net_list
[net_target
] = {'name': "net-"+str(net_nb
), 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1048 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1049 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1050 if iface_type
=='mgmt' or iface_type
=='bridge':
1051 net_type_bridge
= True
1053 net_type_data
= True
1054 if net_type_bridge
and net_type_data
:
1055 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1056 print "nfvo.new_scenario " + error_text
1057 return -HTTP_Bad_Request
, error_text
1058 elif net_type_bridge
:
1061 type_
='data' if len(con
)>2 else 'ptp'
1062 net_list
[net_target
]['type'] = type_
1065 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1066 print "nfvo.new_scenario " + error_text
1068 return -HTTP_Bad_Request
, error_text
1070 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1071 #1.8.1 obtain management net
1072 r
,mgmt_net
= mydb
.get_table(SELECT
=('uuid','name','description','type','shared'),
1073 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1074 #1.8.2 check all interfaces from all vnfs
1076 add_mgmt_net
= False
1077 for vnf
in vnfs
.values():
1078 for iface
in vnf
['ifaces'].values():
1079 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1080 #iface not connected
1081 iface
['net_key'] = 'mgmt'
1083 if add_mgmt_net
and 'mgmt' not in net_list
:
1084 net_list
['mgmt']=mgmt_net
[0]
1085 net_list
['mgmt']['external']=True
1086 net_list
['mgmt']['graph']={'visible':False}
1088 net_list
.update(other_nets
)
1090 print 'net_list', net_list
1095 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1096 r
,c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1097 'tenant_id':tenant_id
, 'name':topo
['name'], 'description':topo
.get('description',topo
['name']) } )
1101 def new_scenario_v02(mydb
, tenant_id
, 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_model' in vnf
:
1123 error_text
+= " 'vnf_model' " + vnf
['vnf_model']
1124 WHERE_
['name'] = vnf
['vnf_model']
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 af
.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']
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 af
.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']
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 af
.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 af
.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 af
.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 af
.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 af
.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 af
.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 af
.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 af
.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 af
.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
)
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 af
.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 af
.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"]
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 af
.check_valid_uuid(datacenter
):
2371 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2373 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2375 print "nfvo.datacenter_action() error. Datacenter not found"
2378 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2380 print "nfvo.datacenter_action() error. Several datacenters found"
2381 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2382 datacenter_id
=vims
.keys()[0]
2383 myvim
=vims
[datacenter_id
]
2385 if not af
.check_valid_uuid(name
):
2386 result
, content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2389 return result
, content
2390 items
= content
.values()[0]
2391 if type(items
)==list and len(items
)==0:
2392 return -HTTP_Not_Found
, "Not found " + item
2393 elif type(items
)==list and len(items
)>1:
2394 return -HTTP_Not_Found
, "Found more than one %s with this name. Use uuid." % item
2395 else: # it is a dict
2396 item_id
= items
["id"]
2397 item_name
= str(items
.get("name"))
2399 if item
=="networks":
2400 result
, content
= myvim
.delete_tenant_network(item_id
)
2401 elif item
=="tenants":
2402 result
, content
= myvim
.delete_tenant(item_id
)
2404 return -HTTP_Method_Not_Allowed
, item
+ "?"
2406 print "vim_action Not possible to delete %s %s from VIM: %s " % (item
, name
, content
)
2407 return result
, content
2408 return 200, "%s %s %s deleted" %( item
[:-1], item_id
,item_name
)
2410 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2411 #get datacenter info
2412 print "vim_action_create descriptor", descriptor
2413 if af
.check_valid_uuid(datacenter
):
2414 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2416 result
, vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2418 print "nfvo.datacenter_action() error. Datacenter not found"
2421 return -HTTP_Not_Found
, "datacenter '%s' not found" % str(datacenter
)
2423 print "nfvo.datacenter_action() error. Several datacenters found"
2424 return -HTTP_Conflict
, "More than one datacenters found, try to identify with uuid"
2425 datacenter_id
=vims
.keys()[0]
2426 myvim
=vims
[datacenter_id
]
2428 if item
=="networks":
2429 net
= descriptor
["network"]
2430 net_name
= net
.pop("name")
2431 net_type
= net
.pop("type", "bridge")
2432 net_public
=net
.pop("shared", False)
2433 result
, content
= myvim
.new_tenant_network(net_name
, net_type
, net_public
, **net
)
2434 elif item
=="tenants":
2435 tenant
= descriptor
["tenant"]
2436 result
, content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2438 return -HTTP_Method_Not_Allowed
, item
+ "?"
2440 print "vim_action Not possible to create %s at VIM: %s " % (item
, content
)
2441 return result
, content
2442 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)