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