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
= "'topology':'nodes':'" + 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 model' 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
})
1324 if sce_net
['vim_id'] == None:
1325 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1326 _
, message
= rollback(mydb
, vims
, rollbackList
)
1327 logger
.error("nfvo.start_scenario: %s", error_text
)
1328 raise NfvoException(error_text
, HTTP_Bad_Request
)
1329 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1330 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1332 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1333 #For each vnf net, we create it and we add it to instanceNetlist.
1334 for sce_vnf
in scenarioDict
['vnfs']:
1335 for net
in sce_vnf
['nets']:
1336 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1338 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1339 myNetName
= myNetName
[0:255] #limit length
1340 myNetType
= net
['type']
1342 myNetDict
["name"] = myNetName
1343 myNetDict
["type"] = myNetType
1344 myNetDict
["tenant_id"] = myvim_tenant
1345 myNetIPProfile
= net
.get('ip_profile', None)
1348 #We should use the dictionary as input parameter for new_network
1349 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1350 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1351 net
['vim_id'] = network_id
1352 if sce_vnf
['uuid'] not in auxNetDict
:
1353 auxNetDict
[sce_vnf
['uuid']] = {}
1354 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1355 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1357 #print "auxNetDict:"
1358 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1360 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1361 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1363 for sce_vnf
in scenarioDict
['vnfs']:
1364 for vm
in sce_vnf
['vms']:
1367 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1368 myVMDict
['name'] = "%s.%s.%d" % (instance_scenario_name
,sce_vnf
['name'],i
)
1369 #myVMDict['description'] = vm['description']
1370 myVMDict
['description'] = myVMDict
['name'][0:99]
1372 myVMDict
['start'] = "no"
1373 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1374 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1376 #create image at vim in case it not exist
1377 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1378 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1379 vm
['vim_image_id'] = image_id
1381 #create flavor at vim in case it not exist
1382 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1383 if flavor_dict
['extended']!=None:
1384 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1385 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1386 vm
['vim_flavor_id'] = flavor_id
1389 myVMDict
['imageRef'] = vm
['vim_image_id']
1390 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1391 myVMDict
['networks'] = []
1392 for iface
in vm
['interfaces']:
1394 if iface
['type']=="data":
1395 netDict
['type'] = iface
['model']
1396 elif "model" in iface
and iface
["model"]!=None:
1397 netDict
['model']=iface
['model']
1398 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1399 #discover type of interface looking at flavor
1400 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1401 for flavor_iface
in numa
.get('interfaces',[]):
1402 if flavor_iface
.get('name') == iface
['internal_name']:
1403 if flavor_iface
['dedicated'] == 'yes':
1404 netDict
['type']="PF" #passthrough
1405 elif flavor_iface
['dedicated'] == 'no':
1406 netDict
['type']="VF" #siov
1407 elif flavor_iface
['dedicated'] == 'yes:sriov':
1408 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1409 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1411 netDict
["use"]=iface
['type']
1412 if netDict
["use"]=="data" and not netDict
.get("type"):
1413 #print "netDict", netDict
1414 #print "iface", iface
1415 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'])
1416 if flavor_dict
.get('extended')==None:
1417 raise NfvoException(e_text
+ "After database migration some information is not available. \
1418 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1420 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1421 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1422 netDict
["type"]="virtual"
1423 if "vpci" in iface
and iface
["vpci"] is not None:
1424 netDict
['vpci'] = iface
['vpci']
1425 if "mac" in iface
and iface
["mac"] is not None:
1426 netDict
['mac_address'] = iface
['mac']
1427 netDict
['name'] = iface
['internal_name']
1428 if iface
['net_id'] is None:
1429 for vnf_iface
in sce_vnf
["interfaces"]:
1432 if vnf_iface
['interface_id']==iface
['uuid']:
1433 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1436 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1437 #skip bridge ifaces not connected to any net
1438 #if 'net_id' not in netDict or netDict['net_id']==None:
1440 myVMDict
['networks'].append(netDict
)
1441 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1442 #print myVMDict['name']
1443 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1444 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1445 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1446 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1447 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1448 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1449 vm
['vim_id'] = vm_id
1450 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1451 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1452 for net
in myVMDict
['networks']:
1454 for iface
in vm
['interfaces']:
1455 if net
["name"]==iface
["internal_name"]:
1456 iface
["vim_id"]=net
["vim_id"]
1459 logger
.debug("start scenario Deployment done")
1460 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1461 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1462 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1463 return mydb
.get_instance_scenario(instance_id
)
1465 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1466 _
, message
= rollback(mydb
, vims
, rollbackList
)
1467 if isinstance(e
, db_base_Exception
):
1468 error_text
= "Exception at database"
1470 error_text
= "Exception at VIM"
1471 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1472 #logger.error("start_scenario %s", error_text)
1473 raise NfvoException(error_text
, e
.http_code
)
1475 def unify_cloud_config(cloud_config
):
1476 index_to_delete
= []
1477 users
= cloud_config
.get("users", [])
1478 for index0
in range(0,len(users
)):
1479 if index0
in index_to_delete
:
1481 for index1
in range(index0
+1,len(users
)):
1482 if index1
in index_to_delete
:
1484 if users
[index0
]["name"] == users
[index1
]["name"]:
1485 index_to_delete
.append(index1
)
1486 for key
in users
[index1
].get("key-pairs",()):
1487 if "key-pairs" not in users
[index0
]:
1488 users
[index0
]["key-pairs"] = [key
]
1489 elif key
not in users
[index0
]["key-pairs"]:
1490 users
[index0
]["key-pairs"].append(key
)
1491 index_to_delete
.sort(reverse
=True)
1492 for index
in index_to_delete
:
1495 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None):
1496 datacenter_id
= None
1497 datacenter_name
= None
1498 if datacenter_id_name
:
1499 if utils
.check_valid_uuid(datacenter_id_name
):
1500 datacenter_id
= datacenter_id_name
1502 datacenter_name
= datacenter_id_name
1503 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
=None)
1505 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1507 #print "nfvo.datacenter_action() error. Several datacenters found"
1508 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1509 return vims
.keys()[0], vims
.values()[0]
1511 def new_scenario_v03(mydb
, tenant_id
, scenario_dict
):
1512 scenario
= scenario_dict
["scenario"]
1513 if tenant_id
!= "any":
1514 check_tenant(mydb
, tenant_id
)
1515 if "tenant_id" in scenario
:
1516 if scenario
["tenant_id"] != tenant_id
:
1517 logger("Tenant '%s' not found", tenant_id
)
1518 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1519 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1523 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1524 for name
,vnf
in scenario
["vnfs"].iteritems():
1526 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1528 error_pos
= "'topology':'nodes':'" + name
+ "'"
1530 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1531 where
['uuid'] = vnf
['vnf_id']
1532 if 'vnf_name' in vnf
:
1533 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1534 where
['name'] = vnf
['vnf_name']
1536 raise NfvoException("Needed a 'vnf_id' or 'VNF model' at " + error_pos
, HTTP_Bad_Request
)
1537 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1543 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1545 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1546 vnf
['uuid']=vnf_db
[0]['uuid']
1547 vnf
['description']=vnf_db
[0]['description']
1549 # get external interfaces
1550 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1551 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1552 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1553 for ext_iface
in ext_ifaces
:
1554 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1556 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1558 #2: Insert net_key and ip_address at every vnf interface
1559 for net_name
,net
in scenario
["networks"].iteritems():
1560 net_type_bridge
=False
1562 for iface_dict
in net
["interfaces"]:
1563 logger
.debug("Iface_dict %s", iface_dict
)
1564 vnf
= iface_dict
["vnf"]
1565 iface
= iface_dict
["vnf_interface"]
1566 if vnf
not in scenario
["vnfs"]:
1567 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1568 #logger.debug(error_text)
1569 raise NfvoException(error_text
, HTTP_Not_Found
)
1570 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1571 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1572 #logger.debug(error_text)
1573 raise NfvoException(error_text
, HTTP_Bad_Request
)
1574 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1575 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1576 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1577 #logger.debug(error_text)
1578 raise NfvoException(error_text
, HTTP_Bad_Request
)
1579 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1580 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['ip_address'] = iface_dict
.get('ip_address',None)
1581 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1582 if iface_type
=='mgmt' or iface_type
=='bridge':
1583 net_type_bridge
= True
1585 net_type_data
= True
1586 if net_type_bridge
and net_type_data
:
1587 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1588 #logger.debug(error_text)
1589 raise NfvoException(error_text
, HTTP_Bad_Request
)
1590 elif net_type_bridge
:
1593 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1595 if ("implementation" in net
):
1596 if (type_
== "bridge" and net
["implementation"] == "underlay"):
1597 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at 'network':'%s'" % (net_name
)
1598 #logger.debug(error_text)
1599 raise NfvoException(error_text
, HTTP_Bad_Request
)
1600 elif (type_
<> "bridge" and net
["implementation"] == "overlay"):
1601 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at 'network':'%s'" % (net_name
)
1602 #logger.debug(error_text)
1603 raise NfvoException(error_text
, HTTP_Bad_Request
)
1604 net
.pop("implementation")
1606 if (type_
== "data" and net
["type"] == "e-line"):
1607 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type 'e-line' at 'network':'%s'" % (net_name
)
1608 #logger.debug(error_text)
1609 raise NfvoException(error_text
, HTTP_Bad_Request
)
1610 elif (type_
== "ptp" and net
["type"] == "e-lan"):
1614 net
['name'] = net_name
1615 net
['external'] = net
.get('external', False)
1617 #3: insert at database
1618 scenario
["nets"] = scenario
["networks"]
1619 scenario
['tenant_id'] = tenant_id
1620 scenario_id
= mydb
.new_scenario2(scenario
)
1624 '''Takes dict d and updates it with the values in dict u.'''
1625 '''It merges all depth levels'''
1626 for k
, v
in u
.iteritems():
1627 if isinstance(v
, collections
.Mapping
):
1628 r
= update(d
.get(k
, {}), v
)
1634 def create_instance(mydb
, tenant_id
, instance_dict
):
1635 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1636 #logger.debug("Creating instance...")
1637 scenario
= instance_dict
["scenario"]
1639 #find main datacenter
1641 datacenter
= instance_dict
.get("datacenter")
1642 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1643 myvims
[default_datacenter_id
] = vim
1644 #myvim_tenant = myvim['tenant_id']
1645 # default_datacenter_name = vim['name']
1646 default_datacenter_tenant_id
= vim
['config']['datacenter_tenant_id'] #TODO review
1649 #print "Checking that the scenario exists and getting the scenario dictionary"
1650 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1652 #logger.debug("Dictionaries before merging")
1653 #logger.debug("InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1654 #logger.debug("ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1656 scenarioDict
['datacenter_tenant_id'] = default_datacenter_tenant_id
1657 scenarioDict
['datacenter_id'] = default_datacenter_id
1659 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1660 auxNetDict
['scenario'] = {}
1662 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1663 instance_name
= instance_dict
["name"]
1664 instance_description
= instance_dict
.get("description")
1666 #0 check correct parameters
1667 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1669 for scenario_net
in scenarioDict
['nets']:
1670 if net_name
== scenario_net
["name"]:
1674 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1675 if "sites" not in net_instance_desc
:
1676 net_instance_desc
["sites"] = [ {} ]
1677 site_without_datacenter_field
= False
1678 for site
in net_instance_desc
["sites"]:
1679 if site
.get("datacenter"):
1680 if site
["datacenter"] not in myvims
:
1681 #Add this datacenter to myvims
1682 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1684 site
["datacenter"] = d
#change name to id
1686 if site_without_datacenter_field
:
1687 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1688 site_without_datacenter_field
= True
1689 site
["datacenter"] = default_datacenter_id
#change name to id
1691 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
1693 for scenario_vnf
in scenarioDict
['vnfs']:
1694 if vnf_name
== scenario_vnf
['name']:
1698 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
1699 if "datacenter" in vnf_instance_desc
:
1700 #Add this datacenter to myvims
1701 if vnf_instance_desc
["datacenter"] not in myvims
:
1702 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
1704 scenario_vnf
["datacenter"] = d
#change name to id
1705 #0.1 parse cloud-config parameters
1706 cloud_config
= scenarioDict
.get("cloud-config", {})
1707 if instance_dict
.get("cloud-config"):
1708 cloud_config
.update( instance_dict
["cloud-config"])
1709 if not cloud_config
:
1712 scenarioDict
["cloud-config"] = cloud_config
1713 unify_cloud_config(cloud_config
)
1715 #0.2 merge instance information into scenario
1716 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
1717 #However, this is not possible yet.
1718 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1719 for scenario_net
in scenarioDict
['nets']:
1720 if net_name
== scenario_net
["name"]:
1721 if 'ip-profile' in net_instance_desc
:
1722 ipprofile
= net_instance_desc
['ip-profile']
1723 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
1724 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
1725 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
1726 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
1727 if 'dhcp' in ipprofile
:
1728 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
1729 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
1730 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
1731 del ipprofile
['dhcp']
1732 update(scenario_net
['ip_profile'],ipprofile
)
1733 for interface
in net_instance_desc
.get('interfaces', () ):
1734 if 'ip_address' in interface
:
1735 for vnf
in scenarioDict
['vnfs']:
1736 if interface
['vnf'] == vnf
['name']:
1737 for vnf_interface
in vnf
['interfaces']:
1738 if interface
['vnf_interface'] == vnf_interface
['external_name']:
1739 vnf_interface
['ip_address']=interface
['ip_address']
1741 #logger.debug("Merged dictionary")
1742 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
1745 #1. Creating new nets (sce_nets) in the VIM"
1746 for sce_net
in scenarioDict
['nets']:
1747 sce_net
["vim_id_sites"]={}
1748 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
1749 net_name
= descriptor_net
.get("vim-network-name")
1750 auxNetDict
['scenario'][sce_net
['uuid']] = {}
1752 sites
= descriptor_net
.get("sites", [ {} ])
1754 if site
.get("datacenter"):
1755 vim
= myvims
[ site
["datacenter"] ]
1756 datacenter_id
= site
["datacenter"]
1758 vim
= myvims
[ default_datacenter_id
]
1759 datacenter_id
= default_datacenter_id
1761 net_type
= sce_net
['type']
1762 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
1763 if sce_net
["external"]:
1765 net_name
= sce_net
["name"]
1766 if "netmap-use" in site
or "netmap-create" in site
:
1767 create_network
= False
1768 lookfor_network
= False
1769 if "netmap-use" in site
:
1770 lookfor_network
= True
1771 if utils
.check_valid_uuid(site
["netmap-use"]):
1772 filter_text
= "scenario id '%s'" % site
["netmap-use"]
1773 lookfor_filter
["id"] = site
["netmap-use"]
1775 filter_text
= "scenario name '%s'" % site
["netmap-use"]
1776 lookfor_filter
["name"] = site
["netmap-use"]
1777 if "netmap-create" in site
:
1778 create_network
= True
1779 net_vim_name
= net_name
1780 if site
["netmap-create"]:
1781 net_vim_name
= site
["netmap-create"]
1783 elif sce_net
['vim_id'] != None:
1784 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
1785 create_network
= False
1786 lookfor_network
= True
1787 lookfor_filter
["id"] = sce_net
['vim_id']
1788 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
1789 #look for network at datacenter and return error
1791 #There is not a netmap, look at datacenter for a net with this name and create if not found
1792 create_network
= True
1793 lookfor_network
= True
1794 lookfor_filter
["name"] = sce_net
["name"]
1795 net_vim_name
= sce_net
["name"]
1796 filter_text
= "scenario name '%s'" % sce_net
["name"]
1799 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
1800 net_name
= net_name
[:255] #limit length
1801 net_vim_name
= net_name
1802 create_network
= True
1803 lookfor_network
= False
1806 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
1807 if len(vim_nets
) > 1:
1808 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1809 elif len(vim_nets
) == 0:
1810 if not create_network
:
1811 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1813 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
1815 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
1816 create_network
= False
1818 #if network is not external
1819 network_id
= vim
.new_network(net_vim_name
, net_type
, sce_net
.get('ip_profile',None))
1820 sce_net
["vim_id_sites"][datacenter_id
] = network_id
1821 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = network_id
1822 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':network_id
})
1824 #2. Creating new nets (vnf internal nets) in the VIM"
1825 #For each vnf net, we create it and we add it to instanceNetlist.
1826 for sce_vnf
in scenarioDict
['vnfs']:
1827 for net
in sce_vnf
['nets']:
1828 if sce_vnf
.get("datacenter"):
1829 vim
= myvims
[ sce_vnf
["datacenter"] ]
1830 datacenter_id
= sce_vnf
["datacenter"]
1832 vim
= myvims
[ default_datacenter_id
]
1833 datacenter_id
= default_datacenter_id
1834 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
1835 net_name
= descriptor_net
.get("name")
1837 net_name
= "%s.%s" %(instance_name
, net
["name"])
1838 net_name
= net_name
[:255] #limit length
1839 net_type
= net
['type']
1840 network_id
= vim
.new_network(net_name
, net_type
, net
.get('ip_profile',None))
1841 net
['vim_id'] = network_id
1842 if sce_vnf
['uuid'] not in auxNetDict
:
1843 auxNetDict
[sce_vnf
['uuid']] = {}
1844 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1845 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1847 #print "auxNetDict:"
1848 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1850 #3. Creating new vm instances in the VIM
1851 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1852 for sce_vnf
in scenarioDict
['vnfs']:
1853 if sce_vnf
.get("datacenter"):
1854 vim
= myvims
[ sce_vnf
["datacenter"] ]
1855 datacenter_id
= sce_vnf
["datacenter"]
1857 vim
= myvims
[ default_datacenter_id
]
1858 datacenter_id
= default_datacenter_id
1859 sce_vnf
["datacenter_id"] = datacenter_id
1860 sce_vnf
["datacenter_tenant_id"] = vim
['config']['datacenter_tenant_id']
1862 for vm
in sce_vnf
['vms']:
1865 myVMDict
['name'] = "%s.%s.%d" % (instance_name
,sce_vnf
['name'],i
)
1866 myVMDict
['description'] = myVMDict
['name'][0:99]
1868 # myVMDict['start'] = "no"
1869 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1870 #create image at vim in case it not exist
1871 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1872 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
1873 vm
['vim_image_id'] = image_id
1875 #create flavor at vim in case it not exist
1876 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1877 if flavor_dict
['extended']!=None:
1878 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1879 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
1880 vm
['vim_flavor_id'] = flavor_id
1882 myVMDict
['imageRef'] = vm
['vim_image_id']
1883 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1884 myVMDict
['networks'] = []
1885 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
1886 for iface
in vm
['interfaces']:
1888 if iface
['type']=="data":
1889 netDict
['type'] = iface
['model']
1890 elif "model" in iface
and iface
["model"]!=None:
1891 netDict
['model']=iface
['model']
1892 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1893 #discover type of interface looking at flavor
1894 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1895 for flavor_iface
in numa
.get('interfaces',[]):
1896 if flavor_iface
.get('name') == iface
['internal_name']:
1897 if flavor_iface
['dedicated'] == 'yes':
1898 netDict
['type']="PF" #passthrough
1899 elif flavor_iface
['dedicated'] == 'no':
1900 netDict
['type']="VF" #siov
1901 elif flavor_iface
['dedicated'] == 'yes:sriov':
1902 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1903 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1905 netDict
["use"]=iface
['type']
1906 if netDict
["use"]=="data" and not netDict
.get("type"):
1907 #print "netDict", netDict
1908 #print "iface", iface
1909 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'])
1910 if flavor_dict
.get('extended')==None:
1911 raise NfvoException(e_text
+ "After database migration some information is not available. \
1912 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1914 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1915 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1916 netDict
["type"]="virtual"
1917 if "vpci" in iface
and iface
["vpci"] is not None:
1918 netDict
['vpci'] = iface
['vpci']
1919 if "mac" in iface
and iface
["mac"] is not None:
1920 netDict
['mac_address'] = iface
['mac']
1921 netDict
['name'] = iface
['internal_name']
1922 if iface
['net_id'] is None:
1923 for vnf_iface
in sce_vnf
["interfaces"]:
1926 if vnf_iface
['interface_id']==iface
['uuid']:
1927 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
1930 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1931 #skip bridge ifaces not connected to any net
1932 #if 'net_id' not in netDict or netDict['net_id']==None:
1934 myVMDict
['networks'].append(netDict
)
1935 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1936 #print myVMDict['name']
1937 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1938 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1939 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1940 vm_id
= vim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1941 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'], cloud_config
= cloud_config
)
1942 vm
['vim_id'] = vm_id
1943 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1944 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1945 for net
in myVMDict
['networks']:
1947 for iface
in vm
['interfaces']:
1948 if net
["name"]==iface
["internal_name"]:
1949 iface
["vim_id"]=net
["vim_id"]
1951 logger
.debug("create_instance Deployment done")
1952 print yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)
1953 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1954 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
1955 return mydb
.get_instance_scenario(instance_id
)
1956 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
1957 message
= rollback(mydb
, myvims
, rollbackList
)
1958 if isinstance(e
, db_base_Exception
):
1959 error_text
= "database Exception"
1960 elif isinstance(e
, vimconn
.vimconnException
):
1961 error_text
= "VIM Exception"
1963 error_text
= "Exception"
1964 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1965 #logger.error("create_instance: %s", error_text)
1966 raise NfvoException(error_text
, e
.http_code
)
1968 def delete_instance(mydb
, tenant_id
, instance_id
):
1969 #print "Checking that the instance_id exists and getting the instance dictionary"
1970 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
1971 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
1972 tenant_id
= instanceDict
["tenant_id"]
1973 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1975 vims
= get_vim(mydb
, tenant_id
, instanceDict
['datacenter_id'])
1977 logger
.error("!!!!!! nfvo.delete_instance() datacenter not found!!!!")
1980 myvim
= vims
.values()[0]
1981 except NfvoException
as e
:
1982 logger
.error("!!!!!! nfvo.delete_instance() datacenter Exception!!!! " + str(e
))
1986 #1. Delete from Database
1988 #result,c = mydb.delete_row_by_id('instance_scenarios', instance_id, nfvo_tenant)
1989 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
1993 error_msg
= "Not possible to delete VIM VMs and networks. Datacenter not found at database!!!"
1999 for sce_vnf
in instanceDict
['vnfs']:
2002 for vm
in sce_vnf
['vms']:
2004 myvim
.delete_vminstance(vm
['vim_vm_id'])
2005 except vimconn
.vimconnNotFoundException
as e
:
2006 error_msg
+="\n VM id={} not found at VIM".format(vm
['vim_vm_id'])
2007 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2008 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2009 except vimconn
.vimconnException
as e
:
2010 error_msg
+="\n Error: " + e
.http_code
+ " VM id=" + vm
['vim_vm_id']
2011 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s': %s",
2012 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2016 for net
in instanceDict
['nets']:
2018 continue #skip not created nets
2022 myvim
.delete_network(net
['vim_net_id'])
2023 except vimconn
.vimconnNotFoundException
as e
:
2024 error_msg
+="\n NET id={} not found at VIM".format(net
['vim_net_id'])
2025 logger
.warn("NET '%s', VIM id '%s', from VNF_id '%s' not found",
2026 net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'])
2027 except vimconn
.vimconnException
as e
:
2028 error_msg
+="\n Error: " + e
.http_code
+ " Net id=" + net
['vim_vm_id']
2029 logger
.error("Error %d deleting NET '%s', VIM id '%s', from VNF_id '%s': %s",
2030 e
.http_code
, net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'], str(e
))
2031 if len(error_msg
)>0:
2032 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2034 return 'instance ' + message
+ ' deleted'
2036 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2037 '''Refreshes a scenario instance. It modifies instanceDict'''
2039 - 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
2042 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2043 #print "nfvo.refresh_instance begins"
2044 #print json.dumps(instanceDict, indent=4)
2046 #print "Getting the VIM URL and the VIM tenant_id"
2047 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2049 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2050 myvim
= vims
.values()[0]
2052 # 1. Getting VIM vm and net list
2053 vms_updated
= [] #List of VM instance uuids in openmano that were updated
2056 for sce_vnf
in instanceDict
['vnfs']:
2057 for vm
in sce_vnf
['vms']:
2058 vm_list
.append(vm
['vim_vm_id'])
2059 vms_notupdated
.append(vm
["uuid"])
2061 nets_updated
= [] #List of VM instance uuids in openmano that were updated
2064 for net
in instanceDict
['nets']:
2065 net_list
.append(net
['vim_net_id'])
2066 nets_notupdated
.append(net
["uuid"])
2069 # 1. Getting the status of all VMs
2070 vm_dict
= myvim
.refresh_vms_status(vm_list
)
2072 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2073 for sce_vnf
in instanceDict
['vnfs']:
2074 for vm
in sce_vnf
['vms']:
2075 vm_id
= vm
['vim_vm_id']
2076 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
2077 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2078 has_mgmt_iface
= False
2079 for iface
in vm
["interfaces"]:
2080 if iface
["type"]=="mgmt":
2081 has_mgmt_iface
= True
2082 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
2083 vm_dict
[vm_id
]['status'] = "ACTIVE"
2084 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'):
2085 vm
['status'] = vm_dict
[vm_id
]['status']
2086 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
2087 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
2088 # 2.1. Update in openmano DB the VMs whose status changed
2090 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
2091 vms_notupdated
.remove(vm
["uuid"])
2093 vms_updated
.append(vm
["uuid"])
2094 except db_base_Exception
as e
:
2095 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2096 # 2.2. Update in openmano DB the interface VMs
2097 for interface
in interfaces
:
2098 #translate from vim_net_id to instance_net_id
2100 for net
in instanceDict
['nets']:
2101 if net
["vim_net_id"] == interface
["vim_net_id"]:
2102 network_id
= net
["uuid"]
2106 del interface
["vim_net_id"]
2108 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
2109 except db_base_Exception
as e
:
2110 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
2112 # 3. Getting the status of all nets
2113 net_dict
= myvim
.refresh_nets_status(net_list
)
2115 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2116 # TODO: update nets inside a vnf
2117 for net
in instanceDict
['nets']:
2118 net_id
= net
['vim_net_id']
2119 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'):
2120 net
['status'] = net_dict
[net_id
]['status']
2121 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
2122 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
2123 # 5.1. Update in openmano DB the nets whose status changed
2125 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
2126 nets_notupdated
.remove(net
["uuid"])
2128 nets_updated
.append(net
["uuid"])
2129 except db_base_Exception
as e
:
2130 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2131 except vimconn
.vimconnException
as e
:
2132 #logger.error("VIM exception %s %s", type(e).__name__, str(e))
2133 raise NfvoException(str(e
), e
.http_code
)
2135 # Returns appropriate output
2136 #print "nfvo.refresh_instance finishes"
2137 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2138 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
2139 instance_id
= instanceDict
['uuid']
2140 if len(vms_notupdated
)+len(nets_notupdated
)>0:
2141 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
2142 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
2144 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2146 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2147 #print "Checking that the instance_id exists and getting the instance dictionary"
2148 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2149 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2151 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2152 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2154 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2155 myvim
= vims
.values()[0]
2158 input_vnfs
= action_dict
.pop("vnfs", [])
2159 input_vms
= action_dict
.pop("vms", [])
2160 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2164 for sce_vnf
in instanceDict
['vnfs']:
2165 for vm
in sce_vnf
['vms']:
2166 if not action_over_all
:
2167 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2168 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2171 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2172 if "console" in action_dict
:
2173 if not global_config
["http_console_proxy"]:
2174 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2175 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2176 protocol
=data
["protocol"],
2177 ip
= data
["server"],
2178 port
= data
["port"],
2179 suffix
= data
["suffix"]),
2183 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2184 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2185 "description": "this console is only reachable by local interface",
2190 #print "console data", data
2192 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2193 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2194 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2195 protocol
=data
["protocol"],
2196 ip
= global_config
["http_console_host"],
2197 port
= console_thread
.port
,
2198 suffix
= data
["suffix"]),
2202 except NfvoException
as e
:
2203 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2207 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2209 except vimconn
.vimconnException
as e
:
2210 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2213 if vm_ok
==0: #all goes wrong
2218 def create_or_use_console_proxy_thread(console_server
, console_port
):
2219 #look for a non-used port
2220 console_thread_key
= console_server
+ ":" + str(console_port
)
2221 if console_thread_key
in global_config
["console_thread"]:
2222 #global_config["console_thread"][console_thread_key].start_timeout()
2223 return global_config
["console_thread"][console_thread_key
]
2225 for port
in global_config
["console_port_iterator"]():
2226 #print "create_or_use_console_proxy_thread() port:", port
2227 if port
in global_config
["console_ports"]:
2230 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2232 global_config
["console_thread"][console_thread_key
] = clithread
2233 global_config
["console_ports"][port
] = console_thread_key
2235 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2236 #port used, try with onoher
2238 except cli
.ConsoleProxyException
as e
:
2239 raise NfvoException(str(e
), HTTP_Bad_Request
)
2240 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2242 def check_tenant(mydb
, tenant_id
):
2243 '''check that tenant exists at database'''
2244 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2246 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2249 def new_tenant(mydb
, tenant_dict
):
2250 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2253 def delete_tenant(mydb
, tenant
):
2254 #get nfvo_tenant info
2256 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2257 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2258 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2260 def new_datacenter(mydb
, datacenter_descriptor
):
2261 if "config" in datacenter_descriptor
:
2262 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2263 #Check that datacenter-type is correct
2264 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2267 module
= "vimconn_" + datacenter_type
2268 module_info
= imp
.find_module(module
)
2269 except (IOError, ImportError):
2270 if module_info
and module_info
[0]:
2271 file.close(module_info
[0])
2272 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2274 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2275 return datacenter_id
2277 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2278 #obtain data, check that only one exist
2279 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2281 datacenter_id
= datacenter
['uuid']
2282 where
={'uuid': datacenter
['uuid']}
2283 if "config" in datacenter_descriptor
:
2284 if datacenter_descriptor
['config']!=None:
2286 new_config_dict
= datacenter_descriptor
["config"]
2289 for k
in new_config_dict
:
2290 if new_config_dict
[k
]==None:
2293 config_dict
= yaml
.load(datacenter
["config"])
2294 config_dict
.update(new_config_dict
)
2298 except Exception as e
:
2299 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2300 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2301 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2302 return datacenter_id
2304 def delete_datacenter(mydb
, datacenter
):
2305 #get nfvo_tenant info
2306 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2307 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2308 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2310 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None):
2311 #get datacenter info
2312 if utils
.check_valid_uuid(datacenter
):
2313 vims
= get_vim(mydb
, datacenter_id
=datacenter
, vim_tenant_name
=vim_tenant_name
, vim_user
=vim_username
, vim_passwd
=vim_password
)
2315 vims
= get_vim(mydb
, datacenter_name
=datacenter
, vim_tenant_name
=vim_tenant_name
, vim_user
=vim_username
, vim_passwd
=vim_password
)
2317 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2319 #print "nfvo.datacenter_action() error. Several datacenters found"
2320 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2322 datacenter_id
=vims
.keys()[0]
2323 myvim
=vims
[datacenter_id
]
2324 datacenter_name
=myvim
["name"]
2326 create_vim_tenant
=True if vim_tenant_id
==None and vim_tenant_name
==None else False
2328 #get nfvo_tenant info
2329 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2330 if vim_tenant_name
==None:
2331 vim_tenant_name
=tenant_dict
['name']
2333 #check that this association does not exist before
2334 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2335 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2336 if len(tenants_datacenters
)>0:
2337 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2339 vim_tenant_id_exist_atdb
=False
2340 if not create_vim_tenant
:
2341 where_
={"datacenter_id": datacenter_id
}
2342 if vim_tenant_id
!=None:
2343 where_
["vim_tenant_id"] = vim_tenant_id
2344 if vim_tenant_name
!=None:
2345 where_
["vim_tenant_name"] = vim_tenant_name
2346 #check if vim_tenant_id is already at database
2347 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2348 if len(datacenter_tenants_dict
)>=1:
2349 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2350 vim_tenant_id_exist_atdb
=True
2351 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2353 datacenter_tenants_dict
= {}
2354 #insert at table datacenter_tenants
2355 else: #if vim_tenant_id==None:
2356 #create tenant at VIM if not provided
2358 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2359 except vimconn
.vimconnException
as e
:
2360 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2361 datacenter_tenants_dict
= {}
2362 datacenter_tenants_dict
["created"]="true"
2364 #fill datacenter_tenants table
2365 if not vim_tenant_id_exist_atdb
:
2366 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2367 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2368 datacenter_tenants_dict
["user"] = vim_username
2369 datacenter_tenants_dict
["passwd"] = vim_password
2370 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2371 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2372 datacenter_tenants_dict
["uuid"] = id_
2374 #fill tenants_datacenters table
2375 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2376 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2377 return datacenter_id
2379 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2380 #get datacenter info
2381 if utils
.check_valid_uuid(datacenter
):
2382 vims
= get_vim(mydb
, datacenter_id
=datacenter
)
2384 vims
= get_vim(mydb
, datacenter_name
=datacenter
)
2386 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2388 #print "nfvo.datacenter_action() error. Several datacenters found"
2389 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2390 datacenter_id
=vims
.keys()[0]
2391 myvim
=vims
[datacenter_id
]
2393 #get nfvo_tenant info
2394 if not tenant_id
or tenant_id
=="any":
2397 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2398 tenant_uuid
= tenant_dict
['uuid']
2400 #check that this association exist before
2401 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2403 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2404 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2405 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2406 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2408 #delete this association
2409 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2411 #get vim_tenant info and deletes
2413 for tenant_datacenter_item
in tenant_datacenter_list
:
2414 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2415 #try to delete vim:tenant
2417 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2418 if vim_tenant_dict
['created']=='true':
2419 #delete tenant at VIM if created by NFVO
2421 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2422 except vimconn
.vimconnException
as e
:
2423 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2424 logger
.warn(warning
)
2425 except db_base_Exception
as e
:
2426 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2427 pass #the error will be caused because dependencies, vim_tenant can not be deleted
2429 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2431 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2433 #get datacenter info
2434 if utils
.check_valid_uuid(datacenter
):
2435 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2437 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2439 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2441 #print "nfvo.datacenter_action() error. Several datacenters found"
2442 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2443 datacenter_id
=vims
.keys()[0]
2444 myvim
=vims
[datacenter_id
]
2446 if 'net-update' in action_dict
:
2448 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2450 except vimconn
.vimconnException
as e
:
2451 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2452 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2453 #update nets Change from VIM format to NFVO format
2456 net_nfvo
={'datacenter_id': datacenter_id
}
2457 net_nfvo
['name'] = net
['name']
2458 #net_nfvo['description']= net['name']
2459 net_nfvo
['vim_net_id'] = net
['id']
2460 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2461 net_nfvo
['shared'] = net
['shared']
2462 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2463 net_list
.append(net_nfvo
)
2464 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2465 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2467 elif 'net-edit' in action_dict
:
2468 net
= action_dict
['net-edit'].pop('net')
2469 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2470 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2471 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2473 elif 'net-delete' in action_dict
:
2474 net
= action_dict
['net-deelte'].get('net')
2475 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2476 result
= mydb
.delete_row(FROM
='datacenter_nets',
2477 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2481 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2483 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2484 #get datacenter info
2485 if utils
.check_valid_uuid(datacenter
):
2486 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2488 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2490 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2492 #print "nfvo.datacenter_action() error. Several datacenters found"
2493 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2494 datacenter_id
=vims
.keys()[0]
2496 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2497 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2498 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2501 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2502 #get datacenter info
2503 if utils
.check_valid_uuid(datacenter
):
2504 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2506 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2508 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2510 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2511 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2512 datacenter_id
=vims
.keys()[0]
2513 myvim
=vims
[datacenter_id
]
2516 action_dict
= action_dict
["netmap"]
2517 if 'vim_id' in action_dict
:
2518 filter_dict
["id"] = action_dict
['vim_id']
2519 if 'vim_name' in action_dict
:
2520 filter_dict
["name"] = action_dict
['vim_name']
2522 filter_dict
["shared"] = True
2525 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
2526 except vimconn
.vimconnException
as e
:
2527 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
2528 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2529 if len(vim_nets
)>1 and action_dict
:
2530 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
2531 elif len(vim_nets
)==0: # and action_dict:
2532 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
2534 for net
in vim_nets
:
2535 net_nfvo
={'datacenter_id': datacenter_id
}
2536 if action_dict
and "name" in action_dict
:
2537 net_nfvo
['name'] = action_dict
['name']
2539 net_nfvo
['name'] = net
['name']
2540 #net_nfvo['description']= net['name']
2541 net_nfvo
['vim_net_id'] = net
['id']
2542 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2543 net_nfvo
['shared'] = net
['shared']
2544 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2546 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2547 net_nfvo
["status"] = "OK"
2548 net_nfvo
["uuid"] = net_id
2549 except db_base_Exception
as e
:
2553 net_nfvo
["status"] = "FAIL: " + str(e
)
2554 net_list
.append(net_nfvo
)
2557 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2558 #get datacenter info
2559 if utils
.check_valid_uuid(datacenter
):
2560 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2562 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2564 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2566 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2567 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2568 datacenter_id
=vims
.keys()[0]
2569 myvim
=vims
[datacenter_id
]
2572 if utils
.check_valid_uuid(name
):
2573 filter_dict
["id"] = name
2575 filter_dict
["name"] = name
2577 if item
=="networks":
2578 #filter_dict['tenant_id'] = myvim['tenant_id']
2579 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2580 elif item
=="tenants":
2581 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2583 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2584 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
2585 if name
and len(content
)==1:
2586 return {item
[:-1]: content
[0]}
2587 elif name
and len(content
)==0:
2588 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
2591 return {item
: content
}
2592 except vimconn
.vimconnException
as e
:
2593 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
2594 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
2596 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
2597 #get datacenter info
2598 if tenant_id
== "any":
2601 if utils
.check_valid_uuid(datacenter
):
2602 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2604 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2606 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2608 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2609 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2610 datacenter_id
=vims
.keys()[0]
2611 myvim
=vims
[datacenter_id
]
2613 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2614 logger
.debug("vim_action_delete vim response: " + str(content
))
2615 items
= content
.values()[0]
2616 if type(items
)==list and len(items
)==0:
2617 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
2618 elif type(items
)==list and len(items
)>1:
2619 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
2620 else: # it is a dict
2621 item_id
= items
["id"]
2622 item_name
= str(items
.get("name"))
2625 if item
=="networks":
2626 content
= myvim
.delete_network(item_id
)
2627 elif item
=="tenants":
2628 content
= myvim
.delete_tenant(item_id
)
2630 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2631 except vimconn
.vimconnException
as e
:
2632 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
2633 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
2635 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
2637 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2638 #get datacenter info
2639 print "vim_action_create descriptor", descriptor
2640 if tenant_id
== "any":
2643 if utils
.check_valid_uuid(datacenter
):
2644 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2646 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2648 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2650 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2651 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2652 datacenter_id
=vims
.keys()[0]
2653 myvim
=vims
[datacenter_id
]
2656 if item
=="networks":
2657 net
= descriptor
["network"]
2658 net_name
= net
.pop("name")
2659 net_type
= net
.pop("type", "bridge")
2660 net_public
= net
.pop("shared", False)
2661 net_ipprofile
= net
.pop("ip_profile", None)
2662 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, **net
)
2663 elif item
=="tenants":
2664 tenant
= descriptor
["tenant"]
2665 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2667 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2668 except vimconn
.vimconnException
as e
:
2669 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
2671 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)