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
46 vimconn_imported
={} #dictionary with VIM type as key, loaded module as value
47 logger
= logging
.getLogger('mano.nfvo')
49 class NfvoException(Exception):
50 def __init__(self
, message
, http_code
):
51 self
.http_code
= http_code
52 Exception.__init
__(self
, message
)
55 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
57 return result, content:
58 <0, error_text upon error
59 nb_records, flavor_list on success
62 WHERE_dict
['vnf_id'] = vnf_id
63 if nfvo_tenant
is not None:
64 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
66 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
67 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
68 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
69 #print "get_flavor_list result:", result
70 #print "get_flavor_list content:", content
72 for flavor
in flavors
:
73 flavorList
.append(flavor
['flavor_id'])
76 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
78 return result, content:
79 <0, error_text upon error
80 nb_records, flavor_list on success
83 WHERE_dict
['vnf_id'] = vnf_id
84 if nfvo_tenant
is not None:
85 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
87 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
88 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
91 imageList
.append(image
['image_id'])
94 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):
95 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
96 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
97 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
98 raise exception upon error
101 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
102 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
103 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
104 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
105 if nfvo_tenant
or vim_tenant
:
106 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'
107 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
108 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
111 from_
= 'datacenters as d'
112 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
114 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
117 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
118 if vim
["config"] != None:
119 extra
.update(yaml
.load(vim
["config"]))
120 if vim
["type"] not in vimconn_imported
:
123 module
= "vimconn_" + vim
["type"]
124 module_info
= imp
.find_module(module
)
125 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
126 vimconn_imported
[vim
["type"]] = vim_conn
127 except (IOError, ImportError) as e
:
128 if module_info
and module_info
[0]:
129 file.close(module_info
[0])
130 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
131 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
135 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
136 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
137 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
138 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
), tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
139 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
140 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
143 except Exception as e
:
144 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
146 except db_base_Exception
as e
:
147 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
149 def rollback(mydb
, vims
, rollback_list
):
151 #delete things by reverse order
152 for i
in range(len(rollback_list
)-1, -1, -1):
153 item
= rollback_list
[i
]
154 if item
["where"]=="vim":
155 if item
["vim_id"] not in vims
:
157 vim
=vims
[ item
["vim_id"] ]
159 if item
["what"]=="image":
160 vim
.delete_image(item
["uuid"])
161 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
162 elif item
["what"]=="flavor":
163 vim
.delete_flavor(item
["uuid"])
164 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
165 elif item
["what"]=="network":
166 vim
.delete_network(item
["uuid"])
167 elif item
["what"]=="vm":
168 vim
.delete_vminstance(item
["uuid"])
169 except vimconn
.vimconnException
as e
:
170 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
171 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
172 except db_base_Exception
as e
:
173 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
177 if item
["what"]=="image":
178 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
179 elif item
["what"]=="flavor":
180 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
181 except db_base_Exception
as e
:
182 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
183 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
184 if len(undeleted_items
)==0:
185 return True," Rollback successful."
187 return False," Rollback fails to delete: " + str(undeleted_items
)
189 def check_vnf_descriptor(vnf_descriptor
):
191 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
193 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
195 #dataplane interfaces
196 for numa
in vnfc
.get("numas",() ):
197 for interface
in numa
.get("interfaces",()):
198 if interface
["name"] in name_list
:
199 raise NfvoException("Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC"\
200 .format(vnfc
["name"], interface
["name"]),
202 name_list
.append( interface
["name"] )
204 for interface
in vnfc
.get("bridge-ifaces",() ):
205 if interface
["name"] in name_list
:
206 raise NfvoException("Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC"\
207 .format(vnfc
["name"], interface
["name"]),
209 name_list
.append( interface
["name"] )
210 vnfc_interfaces
[ vnfc
["name"] ] = name_list
212 #check if the info in external_connections matches with the one in the vnfcs
214 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
215 if external_connection
["name"] in name_list
:
216 raise NfvoException("Error at vnf:external-connections:name, value '{}' already used as an external-connection"\
217 .format(external_connection
["name"]),
219 name_list
.append(external_connection
["name"])
220 if external_connection
["VNFC"] not in vnfc_interfaces
:
221 raise NfvoException("Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC"\
222 .format(external_connection
["name"], external_connection
["VNFC"]),
225 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
226 raise NfvoException("Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC"\
227 .format(external_connection
["name"], external_connection
["local_iface_name"]),
230 #check if the info in internal_connections matches with the one in the vnfcs
232 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
233 if internal_connection
["name"] in name_list
:
234 raise NfvoException("Error at vnf:internal-connections:name, value '%s' already used as an internal-connection"\
235 .format(internal_connection
["name"]),
237 name_list
.append(internal_connection
["name"])
238 #We should check that internal-connections of type "ptp" have only 2 elements
239 if len(internal_connection
["elements"])>2 and internal_connection
["type"] == "ptp":
240 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements, size must be 2 for a type:'ptp'"\
241 .format(internal_connection
["name"]),
243 for port
in internal_connection
["elements"]:
244 if port
["VNFC"] not in vnfc_interfaces
:
245 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC"\
246 .format(internal_connection
["name"], port
["VNFC"]),
248 if port
["local_iface_name"] not in vnfc_interfaces
[ port
["VNFC"] ]:
249 raise NfvoException("Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC"\
250 .format(internal_connection
["name"], port
["local_iface_name"]),
252 return -HTTP_Bad_Request
,
254 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
256 if only_create_at_vim
:
257 image_mano_id
= image_dict
['uuid']
259 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
261 image_mano_id
= images
[0]['uuid']
264 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
265 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None)
267 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
268 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
269 #create image at every vim
270 for vim_id
,vim
in vims
.iteritems():
271 image_created
="false"
273 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
274 #look at VIM if this image exist
276 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
277 except vimconn
.vimconnNotFoundException
as e
:
278 #Create the image in VIM
280 image_vim_id
= vim
.new_image(image_dict
)
281 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
283 except vimconn
.vimconnException
as e
:
285 logger
.error("Error creating image at VIM: %s", str(e
))
287 image_vim_id
= str(e
)
288 logger
.warn("Error creating image at VIM: %s", str(e
))
290 except vimconn
.vimconnException
as e
:
291 logger
.warn("Error contacting VIM to know if the image exist at VIM: %s", str(e
))
292 image_vim_id
= str(e
)
294 #if reach here the image has been create or exist
296 #add new vim_id at datacenters_images
297 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
298 elif image_db
[0]["vim_id"]!=image_vim_id
:
299 #modify existing vim_id at datacenters_images
300 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
302 return image_vim_id
if only_create_at_vim
else image_mano_id
304 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= False):
305 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
306 'ram':flavor_dict
.get('ram'),
307 'vcpus':flavor_dict
.get('vcpus'),
309 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
310 del flavor_dict
['extended']
311 if 'extended' in flavor_dict
:
312 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
314 #look if flavor exist
315 if only_create_at_vim
:
316 flavor_mano_id
= flavor_dict
['uuid']
318 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
320 flavor_mano_id
= flavors
[0]['uuid']
323 #create one by one the images of aditional disks
324 dev_image_list
=[] #list of images
325 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
327 for device
in flavor_dict
['extended'].get('devices',[]):
328 if "image" not in device
:
330 image_dict
={'location':device
['image'], 'name':flavor_dict
['name']+str(dev_nb
)+"-img", 'description':flavor_dict
.get('description')}
331 image_metadata_dict
= device
.get('image metadata', None)
332 image_metadata_str
= None
333 if image_metadata_dict
!= None:
334 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
335 image_dict
['metadata']=image_metadata_str
336 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
337 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
338 dev_image_list
.append(image_id
)
340 temp_flavor_dict
['name'] = flavor_dict
['name']
341 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
342 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
343 flavor_mano_id
= content
344 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
345 #create flavor at every vim
346 if 'uuid' in flavor_dict
:
347 del flavor_dict
['uuid']
349 for vim_id
,vim
in vims
.items():
350 flavor_created
="false"
352 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
353 #look at VIM if this flavor exist SKIPPED
354 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
356 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
360 #Create the flavor in VIM
361 #Translate images at devices from MANO id to VIM id
362 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
363 #make a copy of original devices
365 for device
in flavor_dict
["extended"].get("devices",[]):
368 devices_original
.append(dev
)
369 if 'image' in device
:
371 if 'image metadata' in device
:
372 del device
['image metadata']
374 for index
in range(0,len(devices_original
)) :
375 device
=devices_original
[index
]
376 if "image" not in device
:
378 image_dict
={'location':device
['image'], 'name':flavor_dict
['name']+str(dev_nb
)+"-img", 'description':flavor_dict
.get('description')}
379 image_metadata_dict
= device
.get('image metadata', None)
380 image_metadata_str
= None
381 if image_metadata_dict
!= None:
382 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
383 image_dict
['metadata']=image_metadata_str
384 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
385 image_dict
["uuid"]=image_mano_id
386 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
387 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
390 #check that this vim_id exist in VIM, if not create
391 flavor_vim_id
=flavor_db
[0]["vim_id"]
393 vim
.get_flavor(flavor_vim_id
)
394 continue #flavor exist
395 except vimconn
.vimconnException
:
397 #create flavor at vim
398 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
400 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
401 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
402 flavor_created
="true"
403 except vimconn
.vimconnException
as e
:
405 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
407 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
409 #if reach here the flavor has been create or exist
410 if len(flavor_db
)==0:
411 #add new vim_id at datacenters_flavors
412 mydb
.new_row('datacenters_flavors', {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
, 'created':flavor_created
})
413 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
414 #modify existing vim_id at datacenters_flavors
415 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
417 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
419 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
422 # Step 1. Check the VNF descriptor
423 check_vnf_descriptor(vnf_descriptor
)
424 # Step 2. Check tenant exist
425 if tenant_id
!= "any":
426 check_tenant(mydb
, tenant_id
)
427 if "tenant_id" in vnf_descriptor
["vnf"]:
428 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
429 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
432 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
433 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
434 vims
= get_vim(mydb
, tenant_id
)
438 # Step 4. Review the descriptor and add missing fields
439 #print vnf_descriptor
440 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
441 vnf_name
= vnf_descriptor
['vnf']['name']
442 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
443 if "physical" in vnf_descriptor
['vnf']:
444 del vnf_descriptor
['vnf']['physical']
445 #print vnf_descriptor
446 # Step 5. Check internal connections
447 # TODO: to be moved to step 1????
448 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
449 for ic
in internal_connections
:
450 if len(ic
['elements'])>2 and ic
['type']=='ptp':
451 raise NfvoException("Mismatch 'type':'ptp' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'data'".format(len(ic
), ic
['name']),
453 elif len(ic
['elements'])==2 and ic
['type']=='data':
454 raise NfvoException("Mismatch 'type':'data' with 2 elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'ptp'".format(ic
['name']),
457 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
458 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
459 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
461 #For each VNFC, we add it to the VNFCDict and we create a flavor.
462 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
463 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
465 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
466 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
468 VNFCitem
["name"] = vnfc
['name']
469 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
471 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
474 myflavorDict
["name"] = vnfc
['name']+"-flv"
475 myflavorDict
["description"] = VNFCitem
["description"]
476 myflavorDict
["ram"] = vnfc
.get("ram", 0)
477 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
478 myflavorDict
["disk"] = vnfc
.get("disk", 1)
479 myflavorDict
["extended"] = {}
481 devices
= vnfc
.get("devices")
483 myflavorDict
["extended"]["devices"] = devices
486 # 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
487 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
489 # Previous code has been commented
490 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
491 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
492 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
493 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
495 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
497 # print "Error creating flavor: unknown processor model. Rollback successful."
498 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
500 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
501 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
503 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
504 myflavorDict
['extended']['numas'] = vnfc
['numas']
508 # Step 6.2 New flavors are created in the VIM
509 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
511 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
512 VNFCitem
["flavor_id"] = flavor_id
513 VNFCDict
[vnfc
['name']] = VNFCitem
515 logger
.debug("Creating new images in the VIM for each VNFC")
516 # Step 6.3 New images are created in the VIM
517 #For each VNFC, we must create the appropriate image.
518 #This "for" loop might be integrated with the previous one
519 #In case this integration is made, the VNFCDict might become a VNFClist.
520 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
521 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
522 image_dict
={'location':vnfc
['VNFC image'], 'name':vnfc
['name']+"-img", 'description':VNFCDict
[vnfc
['name']]['description']}
523 image_metadata_dict
= vnfc
.get('image metadata', None)
524 image_metadata_str
= None
525 if image_metadata_dict
is not None:
526 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
527 image_dict
['metadata']=image_metadata_str
528 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
529 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
530 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
531 VNFCDict
[vnfc
['name']]["image_id"] = image_id
532 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
['VNFC image']
535 # Step 7. Storing the VNF descriptor in the repository
536 if "descriptor" not in vnf_descriptor
["vnf"]:
537 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
539 # Step 8. Adding the VNF to the NFVO DB
540 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
542 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
543 _
, message
= rollback(mydb
, vims
, rollback_list
)
544 if isinstance(e
, db_base_Exception
):
545 error_text
= "Exception at database"
546 elif isinstance(e
, KeyError):
547 error_text
= "KeyError exception "
548 e
.http_code
= HTTP_Internal_Server_Error
550 error_text
= "Exception at VIM"
551 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
552 #logger.error("start_scenario %s", error_text)
553 raise NfvoException(error_text
, e
.http_code
)
555 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
558 # Step 1. Check the VNF descriptor
559 check_vnf_descriptor(vnf_descriptor
)
560 # Step 2. Check tenant exist
561 if tenant_id
!= "any":
562 check_tenant(mydb
, tenant_id
)
563 if "tenant_id" in vnf_descriptor
["vnf"]:
564 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
565 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
568 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
569 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
570 vims
= get_vim(mydb
, tenant_id
)
574 # Step 4. Review the descriptor and add missing fields
575 #print vnf_descriptor
576 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
577 vnf_name
= vnf_descriptor
['vnf']['name']
578 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
579 if "physical" in vnf_descriptor
['vnf']:
580 del vnf_descriptor
['vnf']['physical']
581 #print vnf_descriptor
582 # Step 5. Check internal connections
583 # TODO: to be moved to step 1????
584 internal_connections
=vnf_descriptor
['vnf'].get('internal_connections',[])
585 for ic
in internal_connections
:
586 if len(ic
['elements'])>2 and ic
['type']=='e-line':
587 raise NfvoException("Mismatch 'type':'e-line' with {} elements at 'vnf':'internal-conections'['name':'{}']. Change 'type' to 'e-lan'".format(len(ic
), ic
['name']),
590 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
591 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
592 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
594 #For each VNFC, we add it to the VNFCDict and we create a flavor.
595 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
596 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
598 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
599 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
601 VNFCitem
["name"] = vnfc
['name']
602 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
604 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
607 myflavorDict
["name"] = vnfc
['name']+"-flv"
608 myflavorDict
["description"] = VNFCitem
["description"]
609 myflavorDict
["ram"] = vnfc
.get("ram", 0)
610 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
611 myflavorDict
["disk"] = vnfc
.get("disk", 1)
612 myflavorDict
["extended"] = {}
614 devices
= vnfc
.get("devices")
616 myflavorDict
["extended"]["devices"] = devices
619 # 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
620 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
622 # Previous code has been commented
623 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
624 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
625 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
626 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
628 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
630 # print "Error creating flavor: unknown processor model. Rollback successful."
631 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
633 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
634 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
636 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
637 myflavorDict
['extended']['numas'] = vnfc
['numas']
641 # Step 6.2 New flavors are created in the VIM
642 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
644 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
645 VNFCitem
["flavor_id"] = flavor_id
646 VNFCDict
[vnfc
['name']] = VNFCitem
648 logger
.debug("Creating new images in the VIM for each VNFC")
649 # Step 6.3 New images are created in the VIM
650 #For each VNFC, we must create the appropriate image.
651 #This "for" loop might be integrated with the previous one
652 #In case this integration is made, the VNFCDict might become a VNFClist.
653 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
654 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
655 image_dict
={'location':vnfc
['VNFC image'], 'name':vnfc
['name']+"-img", 'description':VNFCDict
[vnfc
['name']]['description']}
656 image_metadata_dict
= vnfc
.get('image metadata', None)
657 image_metadata_str
= None
658 if image_metadata_dict
is not None:
659 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
660 image_dict
['metadata']=image_metadata_str
661 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
662 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
663 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
664 VNFCDict
[vnfc
['name']]["image_id"] = image_id
665 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
['VNFC image']
668 # Step 7. Storing the VNF descriptor in the repository
669 if "descriptor" not in vnf_descriptor
["vnf"]:
670 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
672 # Step 8. Adding the VNF to the NFVO DB
673 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
675 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
676 _
, message
= rollback(mydb
, vims
, rollback_list
)
677 if isinstance(e
, db_base_Exception
):
678 error_text
= "Exception at database"
679 elif isinstance(e
, KeyError):
680 error_text
= "KeyError exception "
681 e
.http_code
= HTTP_Internal_Server_Error
683 error_text
= "Exception at VIM"
684 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
685 #logger.error("start_scenario %s", error_text)
686 raise NfvoException(error_text
, e
.http_code
)
688 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
689 #check valid tenant_id
690 check_tenant(mydb
, tenant_id
)
693 if tenant_id
!= "any":
694 where_or
["tenant_id"] = tenant_id
695 where_or
["public"] = True
696 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
699 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
700 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
701 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
702 data
={'vnf' : filtered_content
}
704 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
705 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description'),
706 WHERE
={'vnfs.uuid': vnf_id
} )
708 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
710 data
['vnf']['VNFC'] = content
711 #TODO: GET all the information from a VNFC and include it in the output.
714 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
715 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
716 WHERE
={'vnfs.uuid': vnf_id
} )
717 data
['vnf']['nets'] = content
719 #GET ip-profile for each net
720 for net
in data
['vnf']['nets']:
721 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
722 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
723 WHERE
={'net_id': net
["uuid"]} )
724 if len(ipprofiles
)==1:
725 net
["ip_profile"] = ipprofiles
[0]
726 elif len(ipprofiles
)>1:
727 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
730 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
732 #GET External Interfaces
733 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
734 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
735 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
736 WHERE
={'vnfs.uuid': vnf_id
},
737 WHERE_NOT
={'interfaces.external_name': None} )
739 data
['vnf']['external-connections'] = content
744 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
746 if tenant_id
!= "any":
747 check_tenant(mydb
, tenant_id
)
748 # Get the URL of the VIM from the nfvo_tenant and the datacenter
749 vims
= get_vim(mydb
, tenant_id
)
753 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
755 if tenant_id
!= "any":
756 where_or
["tenant_id"] = tenant_id
757 where_or
["public"] = True
758 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
761 # "Getting the list of flavors and tenants of the VNF"
762 flavorList
= get_flavorlist(mydb
, vnf_id
)
763 if len(flavorList
)==0:
764 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
766 imageList
= get_imagelist(mydb
, vnf_id
)
767 if len(imageList
)==0:
768 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
770 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
772 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
775 for flavor
in flavorList
:
776 #check if flavor is used by other vnf
778 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
780 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
782 #flavor not used, must be deleted
784 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
786 if flavor_vim
["datacenter_id"] not in vims
:
788 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
790 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
792 myvim
.delete_flavor(flavor_vim
["vim_id"])
793 except vimconn
.vimconnNotFoundException
as e
:
794 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
795 except vimconn
.vimconnException
as e
:
796 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
797 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
798 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
799 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
800 mydb
.delete_row_by_id('flavors', flavor
)
801 except db_base_Exception
as e
:
802 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
803 undeletedItems
.append("flavor %s" % flavor
)
806 for image
in imageList
:
808 #check if image is used by other vnf
809 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
811 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
813 #image not used, must be deleted
815 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
817 if image_vim
["datacenter_id"] not in vims
:
819 if image_vim
['created']=='false': #skip this image because not created by openmano
821 myvim
=vims
[ image_vim
["datacenter_id"] ]
823 myvim
.delete_image(image_vim
["vim_id"])
824 except vimconn
.vimconnNotFoundException
as e
:
825 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
826 except vimconn
.vimconnException
as e
:
827 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
828 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
829 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
830 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
831 mydb
.delete_row_by_id('images', image
)
832 except db_base_Exception
as e
:
833 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
834 undeletedItems
.append("image %s" % image
)
836 return vnf_id
+ " " + vnf
["name"]
838 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
840 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
841 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
845 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
846 myvim
= vims
.values()[0]
847 result
,servers
= myvim
.get_hosts_info()
849 return result
, servers
850 topology
= {'name':myvim
['name'] , 'servers': servers
}
851 return result
, topology
853 def get_hosts(mydb
, nfvo_tenant_id
):
854 vims
= get_vim(mydb
, nfvo_tenant_id
)
856 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
858 #print "nfvo.datacenter_action() error. Several datacenters found"
859 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
860 myvim
= vims
.values()[0]
862 hosts
= myvim
.get_hosts()
863 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
865 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
867 server
={'name':host
['name'], 'vms':[]}
868 for vm
in host
['instances']:
869 #get internal name and model
871 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
872 WHERE
={'vim_vm_id':vm
['id']} )
874 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
876 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
878 except db_base_Exception
as e
:
879 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
880 datacenter
['Datacenters'][0]['servers'].append(server
)
881 #return -400, "en construccion"
883 #print 'datacenters '+ json.dumps(datacenter, indent=4)
885 except vimconn
.vimconnException
as e
:
886 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
888 def new_scenario(mydb
, tenant_id
, topo
):
890 # result, vims = get_vim(mydb, tenant_id)
892 # return result, vims
894 if tenant_id
!= "any":
895 check_tenant(mydb
, tenant_id
)
896 if "tenant_id" in topo
:
897 if topo
["tenant_id"] != tenant_id
:
898 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
903 #1.1: get VNFs and external_networks (other_nets).
905 other_nets
={} #external_networks, bridge_networks and data_networkds
906 nodes
= topo
['topology']['nodes']
907 for k
in nodes
.keys():
908 if nodes
[k
]['type'] == 'VNF':
910 vnfs
[k
]['ifaces'] = {}
911 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
912 other_nets
[k
] = nodes
[k
]
913 other_nets
[k
]['external']=True
914 elif nodes
[k
]['type'] == 'network':
915 other_nets
[k
] = nodes
[k
]
916 other_nets
[k
]['external']=False
919 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
920 for name
,vnf
in vnfs
.items():
922 where_or
={"tenant_id": tenant_id
, 'public': "true"}
924 error_pos
= "'topology':'nodes':'" + name
+ "'"
926 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
927 where
['uuid'] = vnf
['vnf_id']
928 if 'VNF model' in vnf
:
929 error_text
+= " 'VNF model' " + vnf
['VNF model']
930 where
['name'] = vnf
['VNF model']
932 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
934 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
940 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
942 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
943 vnf
['uuid']=vnf_db
[0]['uuid']
944 vnf
['description']=vnf_db
[0]['description']
945 #get external interfaces
946 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
947 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
948 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
949 for ext_iface
in ext_ifaces
:
950 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
952 #1.4 get list of connections
953 conections
= topo
['topology']['connections']
955 for k
in conections
.keys():
956 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
957 ifaces_list
= conections
[k
]['nodes'].items()
958 elif type(conections
[k
]['nodes'])==list: #list with dictionary
960 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
961 for k2
in conection_pair_list
:
964 con_type
= conections
[k
].get("type", "link")
965 if con_type
!= "link":
967 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
968 other_nets
[k
] = {'external': False}
969 if conections
[k
].get("graph"):
970 other_nets
[k
]["graph"] = conections
[k
]["graph"]
971 ifaces_list
.append( (k
, None) )
974 if con_type
== "external_network":
975 other_nets
[k
]['external'] = True
976 if conections
[k
].get("model"):
977 other_nets
[k
]["model"] = conections
[k
]["model"]
979 other_nets
[k
]["model"] = k
980 if con_type
== "dataplane_net" or con_type
== "bridge_net":
981 other_nets
[k
]["model"] = con_type
984 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)
985 #print set(ifaces_list)
986 #check valid VNF and iface names
987 for iface
in ifaces_list
:
988 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
989 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
990 str(k
), iface
[0]), HTTP_Not_Found
)
991 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
992 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
993 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
995 #1.5 unify connections from the pair list to a consolidated list
997 while index
< len(conections_list
):
999 while index2
< len(conections_list
):
1000 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1001 conections_list
[index
] |
= conections_list
[index2
]
1002 del conections_list
[index2
]
1005 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1007 #for k in conections_list:
1012 #1.6 Delete non external nets
1013 # for k in other_nets.keys():
1014 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1015 # for con in conections_list:
1017 # for index in range(0,len(con)):
1018 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1019 # for index in delete_indexes:
1022 #1.7: Check external_ports are present at database table datacenter_nets
1023 for k
,net
in other_nets
.items():
1024 error_pos
= "'topology':'nodes':'" + k
+ "'"
1025 if net
['external']==False:
1026 if 'name' not in net
:
1028 if 'model' not in net
:
1029 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1030 if net
['model']=='bridge_net':
1031 net
['type']='bridge';
1032 elif net
['model']=='dataplane_net':
1035 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1037 #IF we do not want to check that external network exist at datacenter
1042 # if 'net_id' in net:
1043 # error_text += " 'net_id' " + net['net_id']
1044 # WHERE_['uuid'] = net['net_id']
1045 # if 'model' in net:
1046 # error_text += " 'model' " + net['model']
1047 # WHERE_['name'] = net['model']
1048 # if len(WHERE_) == 0:
1049 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1050 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1051 # FROM='datacenter_nets', WHERE=WHERE_ )
1053 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1055 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1056 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1058 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1059 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1060 # other_nets[k].update(net_db[0])
1063 net_nb
=0 #Number of nets
1064 for con
in conections_list
:
1065 #check if this is connected to a external net
1069 for index
in range(0,len(con
)):
1070 #check if this is connected to a external net
1071 for net_key
in other_nets
.keys():
1072 if con
[index
][0]==net_key
:
1073 if other_net_index
>=0:
1074 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1075 #print "nfvo.new_scenario " + error_text
1076 raise NfvoException(error_text
, HTTP_Bad_Request
)
1078 other_net_index
= index
1079 net_target
= net_key
1081 #print "other_net_index", other_net_index
1083 if other_net_index
>=0:
1084 del con
[other_net_index
]
1085 #IF we do not want to check that external network exist at datacenter
1086 if other_nets
[net_target
]['external'] :
1087 if "name" not in other_nets
[net_target
]:
1088 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1089 if other_nets
[net_target
]["type"] == "external_network":
1090 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1091 other_nets
[net_target
]["type"] = "data"
1093 other_nets
[net_target
]["type"] = "bridge"
1095 # if other_nets[net_target]['external'] :
1096 # 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
1097 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1098 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1099 # print "nfvo.new_scenario " + error_text
1100 # return -HTTP_Bad_Request, error_text
1103 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1106 net_type_bridge
=False
1108 net_target
= "__-__net"+str(net_nb
)
1109 net_list
[net_target
] = {'name': "net-"+str(net_nb
), 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1112 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1113 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1114 if iface_type
=='mgmt' or iface_type
=='bridge':
1115 net_type_bridge
= True
1117 net_type_data
= True
1118 if net_type_bridge
and net_type_data
:
1119 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1120 #print "nfvo.new_scenario " + error_text
1121 raise NfvoException(error_text
, HTTP_Bad_Request
)
1122 elif net_type_bridge
:
1125 type_
='data' if len(con
)>2 else 'ptp'
1126 net_list
[net_target
]['type'] = type_
1129 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1130 #print "nfvo.new_scenario " + error_text
1132 raise NfvoException(error_text
, HTTP_Bad_Request
)
1134 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1135 #1.8.1 obtain management net
1136 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1137 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1138 #1.8.2 check all interfaces from all vnfs
1140 add_mgmt_net
= False
1141 for vnf
in vnfs
.values():
1142 for iface
in vnf
['ifaces'].values():
1143 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1144 #iface not connected
1145 iface
['net_key'] = 'mgmt'
1147 if add_mgmt_net
and 'mgmt' not in net_list
:
1148 net_list
['mgmt']=mgmt_net
[0]
1149 net_list
['mgmt']['external']=True
1150 net_list
['mgmt']['graph']={'visible':False}
1152 net_list
.update(other_nets
)
1154 #print 'net_list', net_list
1159 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1160 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1161 'tenant_id':tenant_id
, 'name':topo
['name'],
1162 'description':topo
.get('description',topo
['name']),
1163 'public': topo
.get('public', False)
1168 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
):
1169 scenario
= scenario_dict
["scenario"]
1170 if tenant_id
!= "any":
1171 check_tenant(mydb
, tenant_id
)
1172 if "tenant_id" in scenario
:
1173 if scenario
["tenant_id"] != tenant_id
:
1174 print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1175 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1176 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1180 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1181 for name
,vnf
in scenario
["vnfs"].iteritems():
1183 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1185 error_pos
= "'topology':'nodes':'" + name
+ "'"
1187 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1188 where
['uuid'] = vnf
['vnf_id']
1189 if 'vnf_name' in vnf
:
1190 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1191 where
['name'] = vnf
['vnf_name']
1193 raise NfvoException("Needed a 'vnf_id' or 'VNF model' at " + error_pos
, HTTP_Bad_Request
)
1194 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1200 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1202 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1203 vnf
['uuid']=vnf_db
[0]['uuid']
1204 vnf
['description']=vnf_db
[0]['description']
1206 #get external interfaces
1207 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1208 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1209 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1210 for ext_iface
in ext_ifaces
:
1211 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1213 #2: Insert net_key at every vnf interface
1214 for net_name
,net
in scenario
["networks"].iteritems():
1215 net_type_bridge
=False
1217 for iface_dict
in net
["interfaces"]:
1218 for vnf
,iface
in iface_dict
.iteritems():
1219 if vnf
not in scenario
["vnfs"]:
1220 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1221 #print "nfvo.new_scenario_v02 " + error_text
1222 raise NfvoException(error_text
, HTTP_Not_Found
)
1223 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1224 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1225 #print "nfvo.new_scenario_v02 " + error_text
1226 raise NfvoException(error_text
, HTTP_Bad_Request
)
1227 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1228 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1229 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1230 #print "nfvo.new_scenario_v02 " + error_text
1231 raise NfvoException(error_text
, HTTP_Bad_Request
)
1232 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1233 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1234 if iface_type
=='mgmt' or iface_type
=='bridge':
1235 net_type_bridge
= True
1237 net_type_data
= True
1238 if net_type_bridge
and net_type_data
:
1239 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1240 #print "nfvo.new_scenario " + error_text
1241 raise NfvoException(error_text
, HTTP_Bad_Request
)
1242 elif net_type_bridge
:
1245 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1247 net
['name'] = net_name
1248 net
['external'] = net
.get('external', False)
1250 #3: insert at database
1251 scenario
["nets"] = scenario
["networks"]
1252 scenario
['tenant_id'] = tenant_id
1253 scenario_id
= mydb
.new_scenario( scenario
)
1256 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1257 data
["uuid"] = scenario_id
1258 data
["tenant_id"] = tenant_id
1259 c
= mydb
.edit_scenario( data
)
1262 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1263 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1264 datacenter_id
= None
1265 datacenter_name
=None
1266 if datacenter
!= None:
1267 if utils
.check_valid_uuid(datacenter
):
1268 datacenter_id
= datacenter
1270 datacenter_name
= datacenter
1271 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
)
1273 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
1275 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
1276 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1277 myvim
= vims
.values()[0]
1278 myvim_tenant
= myvim
['tenant_id']
1279 datacenter_id
= myvim
['id']
1280 datacenter_name
= myvim
['name']
1281 datacenter_tenant_id
= myvim
['config']['datacenter_tenant_id']
1284 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1285 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1286 scenarioDict
['datacenter_tenant_id'] = datacenter_tenant_id
1287 scenarioDict
['datacenter_id'] = datacenter_id
1288 #print '================scenarioDict======================='
1289 #print json.dumps(scenarioDict, indent=4)
1290 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1292 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1293 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1295 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1296 auxNetDict
['scenario'] = {}
1298 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1299 for sce_net
in scenarioDict
['nets']:
1300 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1302 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1303 myNetName
= myNetName
[0:255] #limit length
1304 myNetType
= sce_net
['type']
1306 myNetDict
["name"] = myNetName
1307 myNetDict
["type"] = myNetType
1308 myNetDict
["tenant_id"] = myvim_tenant
1309 myNetIPProfile
= sce_net
.get('ip_profile', None)
1311 #We should use the dictionary as input parameter for new_network
1313 if not sce_net
["external"]:
1314 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1315 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1316 sce_net
['vim_id'] = network_id
1317 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1318 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1320 if sce_net
['vim_id'] == None:
1321 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1322 _
, message
= rollback(mydb
, vims
, rollbackList
)
1323 logger
.error("nfvo.start_scenario: %s", error_text
)
1324 raise NfvoException(error_text
, HTTP_Bad_Request
)
1325 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1326 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1328 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1329 #For each vnf net, we create it and we add it to instanceNetlist.
1330 for sce_vnf
in scenarioDict
['vnfs']:
1331 for net
in sce_vnf
['nets']:
1332 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1334 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1335 myNetName
= myNetName
[0:255] #limit length
1336 myNetType
= net
['type']
1338 myNetDict
["name"] = myNetName
1339 myNetDict
["type"] = myNetType
1340 myNetDict
["tenant_id"] = myvim_tenant
1341 myNetIPProfile
= net
.get('ip_profile', None)
1344 #We should use the dictionary as input parameter for new_network
1345 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1346 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1347 net
['vim_id'] = network_id
1348 if sce_vnf
['uuid'] not in auxNetDict
:
1349 auxNetDict
[sce_vnf
['uuid']] = {}
1350 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1351 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1353 #print "auxNetDict:"
1354 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1356 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1357 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1359 for sce_vnf
in scenarioDict
['vnfs']:
1360 for vm
in sce_vnf
['vms']:
1363 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1364 myVMDict
['name'] = "%s.%s.%d" % (instance_scenario_name
,sce_vnf
['name'],i
)
1365 #myVMDict['description'] = vm['description']
1366 myVMDict
['description'] = myVMDict
['name'][0:99]
1368 myVMDict
['start'] = "no"
1369 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1370 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1372 #create image at vim in case it not exist
1373 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1374 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1375 vm
['vim_image_id'] = image_id
1377 #create flavor at vim in case it not exist
1378 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1379 if flavor_dict
['extended']!=None:
1380 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1381 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1382 vm
['vim_flavor_id'] = flavor_id
1385 myVMDict
['imageRef'] = vm
['vim_image_id']
1386 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1387 myVMDict
['networks'] = []
1388 for iface
in vm
['interfaces']:
1390 if iface
['type']=="data":
1391 netDict
['type'] = iface
['model']
1392 elif "model" in iface
and iface
["model"]!=None:
1393 netDict
['model']=iface
['model']
1394 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1395 #discover type of interface looking at flavor
1396 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1397 for flavor_iface
in numa
.get('interfaces',[]):
1398 if flavor_iface
.get('name') == iface
['internal_name']:
1399 if flavor_iface
['dedicated'] == 'yes':
1400 netDict
['type']="PF" #passthrough
1401 elif flavor_iface
['dedicated'] == 'no':
1402 netDict
['type']="VF" #siov
1403 elif flavor_iface
['dedicated'] == 'yes:sriov':
1404 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1405 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1407 netDict
["use"]=iface
['type']
1408 if netDict
["use"]=="data" and not netDict
.get("type"):
1409 #print "netDict", netDict
1410 #print "iface", iface
1411 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'])
1412 if flavor_dict
.get('extended')==None:
1413 raise NfvoException(e_text
+ "After database migration some information is not available. \
1414 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1416 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1417 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1418 netDict
["type"]="virtual"
1419 if "vpci" in iface
and iface
["vpci"] is not None:
1420 netDict
['vpci'] = iface
['vpci']
1421 if "mac" in iface
and iface
["mac"] is not None:
1422 netDict
['mac_address'] = iface
['mac']
1423 netDict
['name'] = iface
['internal_name']
1424 if iface
['net_id'] is None:
1425 for vnf_iface
in sce_vnf
["interfaces"]:
1428 if vnf_iface
['interface_id']==iface
['uuid']:
1429 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1432 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1433 #skip bridge ifaces not connected to any net
1434 #if 'net_id' not in netDict or netDict['net_id']==None:
1436 myVMDict
['networks'].append(netDict
)
1437 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1438 #print myVMDict['name']
1439 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1440 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1441 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1442 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1443 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1444 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1445 vm
['vim_id'] = vm_id
1446 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1447 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1448 for net
in myVMDict
['networks']:
1450 for iface
in vm
['interfaces']:
1451 if net
["name"]==iface
["internal_name"]:
1452 iface
["vim_id"]=net
["vim_id"]
1455 logger
.debug("start scenario Deployment done")
1456 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1457 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1458 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1459 return mydb
.get_instance_scenario(instance_id
)
1461 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1462 _
, message
= rollback(mydb
, vims
, rollbackList
)
1463 if isinstance(e
, db_base_Exception
):
1464 error_text
= "Exception at database"
1466 error_text
= "Exception at VIM"
1467 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1468 #logger.error("start_scenario %s", error_text)
1469 raise NfvoException(error_text
, e
.http_code
)
1471 def unify_cloud_config(cloud_config
):
1472 index_to_delete
= []
1473 users
= cloud_config
.get("users", [])
1474 for index0
in range(0,len(users
)):
1475 if index0
in index_to_delete
:
1477 for index1
in range(index0
+1,len(users
)):
1478 if index1
in index_to_delete
:
1480 if users
[index0
]["name"] == users
[index1
]["name"]:
1481 index_to_delete
.append(index1
)
1482 for key
in users
[index1
].get("key-pairs",()):
1483 if "key-pairs" not in users
[index0
]:
1484 users
[index0
]["key-pairs"] = [key
]
1485 elif key
not in users
[index0
]["key-pairs"]:
1486 users
[index0
]["key-pairs"].append(key
)
1487 index_to_delete
.sort(reverse
=True)
1488 for index
in index_to_delete
:
1491 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None):
1492 datacenter_id
= None
1493 datacenter_name
= None
1494 if datacenter_id_name
:
1495 if utils
.check_valid_uuid(datacenter_id_name
):
1496 datacenter_id
= datacenter_id_name
1498 datacenter_name
= datacenter_id_name
1499 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, vim_tenant
=None)
1501 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1503 #print "nfvo.datacenter_action() error. Several datacenters found"
1504 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1505 return vims
.keys()[0], vims
.values()[0]
1507 def new_scenario_v03(mydb
, tenant_id
, scenario_dict
):
1508 scenario
= scenario_dict
["scenario"]
1509 if tenant_id
!= "any":
1510 check_tenant(mydb
, tenant_id
)
1511 if "tenant_id" in scenario
:
1512 if scenario
["tenant_id"] != tenant_id
:
1513 logger("Tenant '%s' not found", tenant_id
)
1514 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1515 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1519 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1520 for name
,vnf
in scenario
["vnfs"].iteritems():
1522 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1524 error_pos
= "'topology':'nodes':'" + name
+ "'"
1526 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1527 where
['uuid'] = vnf
['vnf_id']
1528 if 'vnf_name' in vnf
:
1529 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1530 where
['name'] = vnf
['vnf_name']
1532 raise NfvoException("Needed a 'vnf_id' or 'VNF model' at " + error_pos
, HTTP_Bad_Request
)
1533 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1539 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1541 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1542 vnf
['uuid']=vnf_db
[0]['uuid']
1543 vnf
['description']=vnf_db
[0]['description']
1545 # get external interfaces
1546 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1547 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1548 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1549 for ext_iface
in ext_ifaces
:
1550 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1552 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1554 #2: Insert net_key and ip_address at every vnf interface
1555 for net_name
,net
in scenario
["networks"].iteritems():
1556 net_type_bridge
=False
1558 for iface_dict
in net
["interfaces"]:
1559 logger
.debug("Iface_dict %s", iface_dict
)
1560 vnf
= iface_dict
["vnf"]
1561 iface
= iface_dict
["vnf_interface"]
1562 if vnf
not in scenario
["vnfs"]:
1563 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1564 #logger.debug(error_text)
1565 raise NfvoException(error_text
, HTTP_Not_Found
)
1566 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1567 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1568 #logger.debug(error_text)
1569 raise NfvoException(error_text
, HTTP_Bad_Request
)
1570 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1571 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1572 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1573 #logger.debug(error_text)
1574 raise NfvoException(error_text
, HTTP_Bad_Request
)
1575 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1576 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['ip_address'] = iface_dict
.get('ip_address',None)
1577 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1578 if iface_type
=='mgmt' or iface_type
=='bridge':
1579 net_type_bridge
= True
1581 net_type_data
= True
1582 if net_type_bridge
and net_type_data
:
1583 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1584 #logger.debug(error_text)
1585 raise NfvoException(error_text
, HTTP_Bad_Request
)
1586 elif net_type_bridge
:
1589 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1591 if ("implementation" in net
):
1592 if (type_
== "bridge" and net
["implementation"] == "underlay"):
1593 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at 'network':'%s'" % (net_name
)
1594 #logger.debug(error_text)
1595 raise NfvoException(error_text
, HTTP_Bad_Request
)
1596 elif (type_
<> "bridge" and net
["implementation"] == "overlay"):
1597 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at 'network':'%s'" % (net_name
)
1598 #logger.debug(error_text)
1599 raise NfvoException(error_text
, HTTP_Bad_Request
)
1600 net
.pop("implementation")
1602 if (type_
== "data" and net
["type"] == "e-line"):
1603 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type 'e-line' at 'network':'%s'" % (net_name
)
1604 #logger.debug(error_text)
1605 raise NfvoException(error_text
, HTTP_Bad_Request
)
1606 elif (type_
== "ptp" and net
["type"] == "e-lan"):
1610 net
['name'] = net_name
1611 net
['external'] = net
.get('external', False)
1613 #3: insert at database
1614 scenario
["nets"] = scenario
["networks"]
1615 scenario
['tenant_id'] = tenant_id
1616 scenario_id
= mydb
.new_scenario2(scenario
)
1620 '''Takes dict d and updates it with the values in dict u.'''
1621 '''It merges all depth levels'''
1622 for k
, v
in u
.iteritems():
1623 if isinstance(v
, collections
.Mapping
):
1624 r
= update(d
.get(k
, {}), v
)
1630 def create_instance(mydb
, tenant_id
, instance_dict
):
1631 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1632 #logger.debug("Creating instance...")
1633 scenario
= instance_dict
["scenario"]
1635 #find main datacenter
1637 datacenter
= instance_dict
.get("datacenter")
1638 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1639 myvims
[default_datacenter_id
] = vim
1640 #myvim_tenant = myvim['tenant_id']
1641 # default_datacenter_name = vim['name']
1642 default_datacenter_tenant_id
= vim
['config']['datacenter_tenant_id'] #TODO review
1645 #print "Checking that the scenario exists and getting the scenario dictionary"
1646 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1648 #logger.debug("Dictionaries before merging")
1649 #logger.debug("InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1650 #logger.debug("ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1652 scenarioDict
['datacenter_tenant_id'] = default_datacenter_tenant_id
1653 scenarioDict
['datacenter_id'] = default_datacenter_id
1655 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1656 auxNetDict
['scenario'] = {}
1658 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1659 instance_name
= instance_dict
["name"]
1660 instance_description
= instance_dict
.get("description")
1662 #0 check correct parameters
1663 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1665 for scenario_net
in scenarioDict
['nets']:
1666 if net_name
== scenario_net
["name"]:
1670 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1671 if "sites" not in net_instance_desc
:
1672 net_instance_desc
["sites"] = [ {} ]
1673 site_without_datacenter_field
= False
1674 for site
in net_instance_desc
["sites"]:
1675 if site
.get("datacenter"):
1676 if site
["datacenter"] not in myvims
:
1677 #Add this datacenter to myvims
1678 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1680 site
["datacenter"] = d
#change name to id
1682 if site_without_datacenter_field
:
1683 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1684 site_without_datacenter_field
= True
1685 site
["datacenter"] = default_datacenter_id
#change name to id
1687 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
1689 for scenario_vnf
in scenarioDict
['vnfs']:
1690 if vnf_name
== scenario_vnf
['name']:
1694 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
1695 if "datacenter" in vnf_instance_desc
:
1696 #Add this datacenter to myvims
1697 if vnf_instance_desc
["datacenter"] not in myvims
:
1698 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
1700 scenario_vnf
["datacenter"] = d
#change name to id
1701 #0.1 parse cloud-config parameters
1702 cloud_config
= scenarioDict
.get("cloud-config", {})
1703 if instance_dict
.get("cloud-config"):
1704 cloud_config
.update( instance_dict
["cloud-config"])
1705 if not cloud_config
:
1708 scenarioDict
["cloud-config"] = cloud_config
1709 unify_cloud_config(cloud_config
)
1711 #0.2 merge instance information into scenario
1712 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
1713 #However, this is not possible yet.
1714 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1715 for scenario_net
in scenarioDict
['nets']:
1716 if net_name
== scenario_net
["name"]:
1717 if 'ip-profile' in net_instance_desc
:
1718 ipprofile
= net_instance_desc
['ip-profile']
1719 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
1720 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
1721 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
1722 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
1723 if 'dhcp' in ipprofile
:
1724 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
1725 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
1726 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
1727 del ipprofile
['dhcp']
1728 update(scenario_net
['ip_profile'],ipprofile
)
1729 for interface
in net_instance_desc
['interfaces']:
1730 if 'ip_address' in interface
:
1731 for vnf
in scenarioDict
['vnfs']:
1732 if interface
['vnf'] == vnf
['name']:
1733 for vnf_interface
in vnf
['interfaces']:
1734 if interface
['vnf_interface'] == vnf_interface
['external_name']:
1735 vnf_interface
['ip_address']=interface
['ip_address']
1737 #logger.debug("Merged dictionary")
1738 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
1741 #1. Creating new nets (sce_nets) in the VIM"
1742 for sce_net
in scenarioDict
['nets']:
1743 sce_net
["vim_id_sites"]={}
1744 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
1745 net_name
= descriptor_net
.get("vim-network-name")
1746 auxNetDict
['scenario'][sce_net
['uuid']] = {}
1748 sites
= descriptor_net
.get("sites", [ {} ])
1750 if site
.get("datacenter"):
1751 vim
= myvims
[ site
["datacenter"] ]
1752 datacenter_id
= site
["datacenter"]
1754 vim
= myvims
[ default_datacenter_id
]
1755 datacenter_id
= default_datacenter_id
1757 net_type
= sce_net
['type']
1758 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
1759 if sce_net
["external"]:
1761 net_name
= sce_net
["name"]
1762 if "netmap-use" in site
or "netmap-create" in site
:
1763 create_network
= False
1764 lookfor_network
= False
1765 if "netmap-use" in site
:
1766 lookfor_network
= True
1767 if utils
.check_valid_uuid(site
["netmap-use"]):
1768 filter_text
= "scenario id '%s'" % site
["netmap-use"]
1769 lookfor_filter
["id"] = site
["netmap-use"]
1771 filter_text
= "scenario name '%s'" % site
["netmap-use"]
1772 lookfor_filter
["name"] = site
["netmap-use"]
1773 if "netmap-create" in site
:
1774 create_network
= True
1775 net_vim_name
= net_name
1776 if site
["netmap-create"]:
1777 net_vim_name
= site
["netmap-create"]
1779 elif sce_net
['vim_id'] != None:
1780 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
1781 create_network
= False
1782 lookfor_network
= True
1783 lookfor_filter
["id"] = sce_net
['vim_id']
1784 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
1785 #look for network at datacenter and return error
1787 #There is not a netmap, look at datacenter for a net with this name and create if not found
1788 create_network
= True
1789 lookfor_network
= True
1790 lookfor_filter
["name"] = sce_net
["name"]
1791 net_vim_name
= sce_net
["name"]
1792 filter_text
= "scenario name '%s'" % sce_net
["name"]
1795 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
1796 net_name
= net_name
[:255] #limit length
1797 net_vim_name
= net_name
1798 create_network
= True
1799 lookfor_network
= False
1802 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
1803 if len(vim_nets
) > 1:
1804 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1805 elif len(vim_nets
) == 0:
1806 if not create_network
:
1807 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
1809 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
1811 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
1812 create_network
= False
1814 #if network is not external
1815 network_id
= vim
.new_network(net_vim_name
, net_type
, sce_net
.get('ip_profile',None))
1816 sce_net
["vim_id_sites"][datacenter_id
] = network_id
1817 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = network_id
1818 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':network_id
})
1820 #2. Creating new nets (vnf internal nets) in the VIM"
1821 #For each vnf net, we create it and we add it to instanceNetlist.
1822 for sce_vnf
in scenarioDict
['vnfs']:
1823 for net
in sce_vnf
['nets']:
1824 if sce_vnf
.get("datacenter"):
1825 vim
= myvims
[ sce_vnf
["datacenter"] ]
1826 datacenter_id
= sce_vnf
["datacenter"]
1828 vim
= myvims
[ default_datacenter_id
]
1829 datacenter_id
= default_datacenter_id
1830 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
1831 net_name
= descriptor_net
.get("name")
1833 net_name
= "%s.%s" %(instance_name
, net
["name"])
1834 net_name
= net_name
[:255] #limit length
1835 net_type
= net
['type']
1836 network_id
= vim
.new_network(net_name
, net_type
, net
.get('ip_profile',None))
1837 net
['vim_id'] = network_id
1838 if sce_vnf
['uuid'] not in auxNetDict
:
1839 auxNetDict
[sce_vnf
['uuid']] = {}
1840 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1841 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1843 #print "auxNetDict:"
1844 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1846 #3. Creating new vm instances in the VIM
1847 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1848 for sce_vnf
in scenarioDict
['vnfs']:
1849 if sce_vnf
.get("datacenter"):
1850 vim
= myvims
[ sce_vnf
["datacenter"] ]
1851 datacenter_id
= sce_vnf
["datacenter"]
1853 vim
= myvims
[ default_datacenter_id
]
1854 datacenter_id
= default_datacenter_id
1855 sce_vnf
["datacenter_id"] = datacenter_id
1856 sce_vnf
["datacenter_tenant_id"] = vim
['config']['datacenter_tenant_id']
1858 for vm
in sce_vnf
['vms']:
1861 myVMDict
['name'] = "%s.%s.%d" % (instance_name
,sce_vnf
['name'],i
)
1862 myVMDict
['description'] = myVMDict
['name'][0:99]
1864 # myVMDict['start'] = "no"
1865 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1866 #create image at vim in case it not exist
1867 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1868 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
1869 vm
['vim_image_id'] = image_id
1871 #create flavor at vim in case it not exist
1872 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1873 if flavor_dict
['extended']!=None:
1874 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1875 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
1876 vm
['vim_flavor_id'] = flavor_id
1878 myVMDict
['imageRef'] = vm
['vim_image_id']
1879 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1880 myVMDict
['networks'] = []
1881 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
1882 for iface
in vm
['interfaces']:
1884 if iface
['type']=="data":
1885 netDict
['type'] = iface
['model']
1886 elif "model" in iface
and iface
["model"]!=None:
1887 netDict
['model']=iface
['model']
1888 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1889 #discover type of interface looking at flavor
1890 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1891 for flavor_iface
in numa
.get('interfaces',[]):
1892 if flavor_iface
.get('name') == iface
['internal_name']:
1893 if flavor_iface
['dedicated'] == 'yes':
1894 netDict
['type']="PF" #passthrough
1895 elif flavor_iface
['dedicated'] == 'no':
1896 netDict
['type']="VF" #siov
1897 elif flavor_iface
['dedicated'] == 'yes:sriov':
1898 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1899 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1901 netDict
["use"]=iface
['type']
1902 if netDict
["use"]=="data" and not netDict
.get("type"):
1903 #print "netDict", netDict
1904 #print "iface", iface
1905 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'])
1906 if flavor_dict
.get('extended')==None:
1907 raise NfvoException(e_text
+ "After database migration some information is not available. \
1908 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1910 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1911 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1912 netDict
["type"]="virtual"
1913 if "vpci" in iface
and iface
["vpci"] is not None:
1914 netDict
['vpci'] = iface
['vpci']
1915 if "mac" in iface
and iface
["mac"] is not None:
1916 netDict
['mac_address'] = iface
['mac']
1917 netDict
['name'] = iface
['internal_name']
1918 if iface
['net_id'] is None:
1919 for vnf_iface
in sce_vnf
["interfaces"]:
1922 if vnf_iface
['interface_id']==iface
['uuid']:
1923 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
1926 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1927 #skip bridge ifaces not connected to any net
1928 #if 'net_id' not in netDict or netDict['net_id']==None:
1930 myVMDict
['networks'].append(netDict
)
1931 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1932 #print myVMDict['name']
1933 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1934 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1935 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1936 vm_id
= vim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1937 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'], cloud_config
= cloud_config
)
1938 vm
['vim_id'] = vm_id
1939 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1940 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1941 for net
in myVMDict
['networks']:
1943 for iface
in vm
['interfaces']:
1944 if net
["name"]==iface
["internal_name"]:
1945 iface
["vim_id"]=net
["vim_id"]
1947 logger
.debug("create_instance Deployment done")
1948 print yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)
1949 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1950 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
1951 return mydb
.get_instance_scenario(instance_id
)
1952 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
1953 message
= rollback(mydb
, myvims
, rollbackList
)
1954 if isinstance(e
, db_base_Exception
):
1955 error_text
= "database Exception"
1956 elif isinstance(e
, vimconn
.vimconnException
):
1957 error_text
= "VIM Exception"
1959 error_text
= "Exception"
1960 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1961 #logger.error("create_instance: %s", error_text)
1962 raise NfvoException(error_text
, e
.http_code
)
1964 def delete_instance(mydb
, tenant_id
, instance_id
):
1965 #print "Checking that the instance_id exists and getting the instance dictionary"
1966 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
1967 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
1968 tenant_id
= instanceDict
["tenant_id"]
1969 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1971 vims
= get_vim(mydb
, tenant_id
, instanceDict
['datacenter_id'])
1973 logger
.error("!!!!!! nfvo.delete_instance() datacenter not found!!!!")
1976 myvim
= vims
.values()[0]
1977 except NfvoException
as e
:
1978 logger
.error("!!!!!! nfvo.delete_instance() datacenter Exception!!!! " + str(e
))
1982 #1. Delete from Database
1984 #result,c = mydb.delete_row_by_id('instance_scenarios', instance_id, nfvo_tenant)
1985 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
1989 error_msg
= "Not possible to delete VIM VMs and networks. Datacenter not found at database!!!"
1995 for sce_vnf
in instanceDict
['vnfs']:
1998 for vm
in sce_vnf
['vms']:
2000 myvim
.delete_vminstance(vm
['vim_vm_id'])
2001 except vimconn
.vimconnNotFoundException
as e
:
2002 error_msg
+="\n VM id={} not found at VIM".format(vm
['vim_vm_id'])
2003 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2004 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2005 except vimconn
.vimconnException
as e
:
2006 error_msg
+="\n Error: " + e
.http_code
+ " VM id=" + vm
['vim_vm_id']
2007 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s': %s",
2008 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2012 for net
in instanceDict
['nets']:
2014 continue #skip not created nets
2018 myvim
.delete_network(net
['vim_net_id'])
2019 except vimconn
.vimconnNotFoundException
as e
:
2020 error_msg
+="\n NET id={} not found at VIM".format(net
['vim_net_id'])
2021 logger
.warn("NET '%s', VIM id '%s', from VNF_id '%s' not found",
2022 net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'])
2023 except vimconn
.vimconnException
as e
:
2024 error_msg
+="\n Error: " + e
.http_code
+ " Net id=" + net
['vim_vm_id']
2025 logger
.error("Error %d deleting NET '%s', VIM id '%s', from VNF_id '%s': %s",
2026 e
.http_code
, net
['uuid'], net
['vim_net_id'], sce_vnf
['vnf_id'], str(e
))
2027 if len(error_msg
)>0:
2028 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2030 return 'instance ' + message
+ ' deleted'
2032 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2033 '''Refreshes a scenario instance. It modifies instanceDict'''
2035 - 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
2038 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2039 #print "nfvo.refresh_instance begins"
2040 #print json.dumps(instanceDict, indent=4)
2042 #print "Getting the VIM URL and the VIM tenant_id"
2043 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2045 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2046 myvim
= vims
.values()[0]
2048 # 1. Getting VIM vm and net list
2049 vms_updated
= [] #List of VM instance uuids in openmano that were updated
2052 for sce_vnf
in instanceDict
['vnfs']:
2053 for vm
in sce_vnf
['vms']:
2054 vm_list
.append(vm
['vim_vm_id'])
2055 vms_notupdated
.append(vm
["uuid"])
2057 nets_updated
= [] #List of VM instance uuids in openmano that were updated
2060 for net
in instanceDict
['nets']:
2061 net_list
.append(net
['vim_net_id'])
2062 nets_notupdated
.append(net
["uuid"])
2065 # 1. Getting the status of all VMs
2066 vm_dict
= myvim
.refresh_vms_status(vm_list
)
2068 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2069 for sce_vnf
in instanceDict
['vnfs']:
2070 for vm
in sce_vnf
['vms']:
2071 vm_id
= vm
['vim_vm_id']
2072 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
2073 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2074 has_mgmt_iface
= False
2075 for iface
in vm
["interfaces"]:
2076 if iface
["type"]=="mgmt":
2077 has_mgmt_iface
= True
2078 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
2079 vm_dict
[vm_id
]['status'] = "ACTIVE"
2080 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'):
2081 vm
['status'] = vm_dict
[vm_id
]['status']
2082 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
2083 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
2084 # 2.1. Update in openmano DB the VMs whose status changed
2086 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
2087 vms_notupdated
.remove(vm
["uuid"])
2089 vms_updated
.append(vm
["uuid"])
2090 except db_base_Exception
as e
:
2091 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2092 # 2.2. Update in openmano DB the interface VMs
2093 for interface
in interfaces
:
2094 #translate from vim_net_id to instance_net_id
2096 for net
in instanceDict
['nets']:
2097 if net
["vim_net_id"] == interface
["vim_net_id"]:
2098 network_id
= net
["uuid"]
2102 del interface
["vim_net_id"]
2104 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
2105 except db_base_Exception
as e
:
2106 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
2108 # 3. Getting the status of all nets
2109 net_dict
= myvim
.refresh_nets_status(net_list
)
2111 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2112 # TODO: update nets inside a vnf
2113 for net
in instanceDict
['nets']:
2114 net_id
= net
['vim_net_id']
2115 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'):
2116 net
['status'] = net_dict
[net_id
]['status']
2117 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
2118 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
2119 # 5.1. Update in openmano DB the nets whose status changed
2121 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
2122 nets_notupdated
.remove(net
["uuid"])
2124 nets_updated
.append(net
["uuid"])
2125 except db_base_Exception
as e
:
2126 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2127 except vimconn
.vimconnException
as e
:
2128 #logger.error("VIM exception %s %s", type(e).__name__, str(e))
2129 raise NfvoException(str(e
), e
.http_code
)
2131 # Returns appropriate output
2132 #print "nfvo.refresh_instance finishes"
2133 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2134 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
2135 instance_id
= instanceDict
['uuid']
2136 if len(vms_notupdated
)+len(nets_notupdated
)>0:
2137 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
2138 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
2140 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2142 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2143 #print "Checking that the instance_id exists and getting the instance dictionary"
2144 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2145 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2147 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2148 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2150 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2151 myvim
= vims
.values()[0]
2154 input_vnfs
= action_dict
.pop("vnfs", [])
2155 input_vms
= action_dict
.pop("vms", [])
2156 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2160 for sce_vnf
in instanceDict
['vnfs']:
2161 for vm
in sce_vnf
['vms']:
2162 if not action_over_all
:
2163 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2164 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2167 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2168 if "console" in action_dict
:
2169 if not global_config
["http_console_proxy"]:
2170 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2171 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2172 protocol
=data
["protocol"],
2173 ip
= data
["server"],
2174 port
= data
["port"],
2175 suffix
= data
["suffix"]),
2179 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2180 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2181 "description": "this console is only reachable by local interface",
2186 #print "console data", data
2188 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2189 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2190 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2191 protocol
=data
["protocol"],
2192 ip
= global_config
["http_console_host"],
2193 port
= console_thread
.port
,
2194 suffix
= data
["suffix"]),
2198 except NfvoException
as e
:
2199 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2203 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2205 except vimconn
.vimconnException
as e
:
2206 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2209 if vm_ok
==0: #all goes wrong
2214 def create_or_use_console_proxy_thread(console_server
, console_port
):
2215 #look for a non-used port
2216 console_thread_key
= console_server
+ ":" + str(console_port
)
2217 if console_thread_key
in global_config
["console_thread"]:
2218 #global_config["console_thread"][console_thread_key].start_timeout()
2219 return global_config
["console_thread"][console_thread_key
]
2221 for port
in global_config
["console_port_iterator"]():
2222 #print "create_or_use_console_proxy_thread() port:", port
2223 if port
in global_config
["console_ports"]:
2226 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2228 global_config
["console_thread"][console_thread_key
] = clithread
2229 global_config
["console_ports"][port
] = console_thread_key
2231 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2232 #port used, try with onoher
2234 except cli
.ConsoleProxyException
as e
:
2235 raise NfvoException(str(e
), HTTP_Bad_Request
)
2236 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2238 def check_tenant(mydb
, tenant_id
):
2239 '''check that tenant exists at database'''
2240 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2242 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2245 def new_tenant(mydb
, tenant_dict
):
2246 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2249 def delete_tenant(mydb
, tenant
):
2250 #get nfvo_tenant info
2252 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2253 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2254 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2256 def new_datacenter(mydb
, datacenter_descriptor
):
2257 if "config" in datacenter_descriptor
:
2258 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2259 #Check that datacenter-type is correct
2260 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2263 module
= "vimconn_" + datacenter_type
2264 module_info
= imp
.find_module(module
)
2265 except (IOError, ImportError):
2266 if module_info
and module_info
[0]:
2267 file.close(module_info
[0])
2268 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2270 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2271 return datacenter_id
2273 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2274 #obtain data, check that only one exist
2275 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2277 datacenter_id
= datacenter
['uuid']
2278 where
={'uuid': datacenter
['uuid']}
2279 if "config" in datacenter_descriptor
:
2280 if datacenter_descriptor
['config']!=None:
2282 new_config_dict
= datacenter_descriptor
["config"]
2285 for k
in new_config_dict
:
2286 if new_config_dict
[k
]==None:
2289 config_dict
= yaml
.load(datacenter
["config"])
2290 config_dict
.update(new_config_dict
)
2294 except Exception as e
:
2295 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2296 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2297 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2298 return datacenter_id
2300 def delete_datacenter(mydb
, datacenter
):
2301 #get nfvo_tenant info
2302 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2303 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2304 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2306 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None):
2307 #get datacenter info
2308 if utils
.check_valid_uuid(datacenter
):
2309 vims
= get_vim(mydb
, datacenter_id
=datacenter
, vim_tenant_name
=vim_tenant_name
, vim_user
=vim_username
, vim_passwd
=vim_password
)
2311 vims
= get_vim(mydb
, datacenter_name
=datacenter
, vim_tenant_name
=vim_tenant_name
, vim_user
=vim_username
, vim_passwd
=vim_password
)
2313 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2315 #print "nfvo.datacenter_action() error. Several datacenters found"
2316 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2318 datacenter_id
=vims
.keys()[0]
2319 myvim
=vims
[datacenter_id
]
2320 datacenter_name
=myvim
["name"]
2322 create_vim_tenant
=True if vim_tenant_id
==None and vim_tenant_name
==None else False
2324 #get nfvo_tenant info
2325 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2326 if vim_tenant_name
==None:
2327 vim_tenant_name
=tenant_dict
['name']
2329 #check that this association does not exist before
2330 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2331 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2332 if len(tenants_datacenters
)>0:
2333 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2335 vim_tenant_id_exist_atdb
=False
2336 if not create_vim_tenant
:
2337 where_
={"datacenter_id": datacenter_id
}
2338 if vim_tenant_id
!=None:
2339 where_
["vim_tenant_id"] = vim_tenant_id
2340 if vim_tenant_name
!=None:
2341 where_
["vim_tenant_name"] = vim_tenant_name
2342 #check if vim_tenant_id is already at database
2343 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2344 if len(datacenter_tenants_dict
)>=1:
2345 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2346 vim_tenant_id_exist_atdb
=True
2347 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2349 datacenter_tenants_dict
= {}
2350 #insert at table datacenter_tenants
2351 else: #if vim_tenant_id==None:
2352 #create tenant at VIM if not provided
2354 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2355 except vimconn
.vimconnException
as e
:
2356 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2357 datacenter_tenants_dict
= {}
2358 datacenter_tenants_dict
["created"]="true"
2360 #fill datacenter_tenants table
2361 if not vim_tenant_id_exist_atdb
:
2362 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2363 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2364 datacenter_tenants_dict
["user"] = vim_username
2365 datacenter_tenants_dict
["passwd"] = vim_password
2366 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2367 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2368 datacenter_tenants_dict
["uuid"] = id_
2370 #fill tenants_datacenters table
2371 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2372 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2373 return datacenter_id
2375 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2376 #get datacenter info
2377 if utils
.check_valid_uuid(datacenter
):
2378 vims
= get_vim(mydb
, datacenter_id
=datacenter
)
2380 vims
= get_vim(mydb
, datacenter_name
=datacenter
)
2382 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2384 #print "nfvo.datacenter_action() error. Several datacenters found"
2385 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2386 datacenter_id
=vims
.keys()[0]
2387 myvim
=vims
[datacenter_id
]
2389 #get nfvo_tenant info
2390 if not tenant_id
or tenant_id
=="any":
2393 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2394 tenant_uuid
= tenant_dict
['uuid']
2396 #check that this association exist before
2397 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2399 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2400 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2401 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2402 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2404 #delete this association
2405 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2407 #get vim_tenant info and deletes
2409 for tenant_datacenter_item
in tenant_datacenter_list
:
2410 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2411 #try to delete vim:tenant
2413 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2414 if vim_tenant_dict
['created']=='true':
2415 #delete tenant at VIM if created by NFVO
2417 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2418 except vimconn
.vimconnException
as e
:
2419 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2420 logger
.warn(warning
)
2421 except db_base_Exception
as e
:
2422 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2423 pass #the error will be caused because dependencies, vim_tenant can not be deleted
2425 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2427 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2429 #get datacenter info
2430 if utils
.check_valid_uuid(datacenter
):
2431 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2433 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2435 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2437 #print "nfvo.datacenter_action() error. Several datacenters found"
2438 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2439 datacenter_id
=vims
.keys()[0]
2440 myvim
=vims
[datacenter_id
]
2442 if 'net-update' in action_dict
:
2444 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2446 except vimconn
.vimconnException
as e
:
2447 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2448 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2449 #update nets Change from VIM format to NFVO format
2452 net_nfvo
={'datacenter_id': datacenter_id
}
2453 net_nfvo
['name'] = net
['name']
2454 #net_nfvo['description']= net['name']
2455 net_nfvo
['vim_net_id'] = net
['id']
2456 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2457 net_nfvo
['shared'] = net
['shared']
2458 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2459 net_list
.append(net_nfvo
)
2460 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2461 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2463 elif 'net-edit' in action_dict
:
2464 net
= action_dict
['net-edit'].pop('net')
2465 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2466 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2467 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2469 elif 'net-delete' in action_dict
:
2470 net
= action_dict
['net-deelte'].get('net')
2471 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2472 result
= mydb
.delete_row(FROM
='datacenter_nets',
2473 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2477 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2479 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2480 #get datacenter info
2481 if utils
.check_valid_uuid(datacenter
):
2482 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2484 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2486 raise NfvoException("datacenter '{}' not found".format(str(datacenter
)), HTTP_Not_Found
)
2488 #print "nfvo.datacenter_action() error. Several datacenters found"
2489 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2490 datacenter_id
=vims
.keys()[0]
2492 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2493 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2494 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2497 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2498 #get datacenter info
2499 if utils
.check_valid_uuid(datacenter
):
2500 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2502 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2504 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2506 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2507 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2508 datacenter_id
=vims
.keys()[0]
2509 myvim
=vims
[datacenter_id
]
2512 action_dict
= action_dict
["netmap"]
2513 if 'vim_id' in action_dict
:
2514 filter_dict
["id"] = action_dict
['vim_id']
2515 if 'vim_name' in action_dict
:
2516 filter_dict
["name"] = action_dict
['vim_name']
2518 filter_dict
["shared"] = True
2521 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
2522 except vimconn
.vimconnException
as e
:
2523 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
2524 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2525 if len(vim_nets
)>1 and action_dict
:
2526 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
2527 elif len(vim_nets
)==0: # and action_dict:
2528 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
2530 for net
in vim_nets
:
2531 net_nfvo
={'datacenter_id': datacenter_id
}
2532 if action_dict
and "name" in action_dict
:
2533 net_nfvo
['name'] = action_dict
['name']
2535 net_nfvo
['name'] = net
['name']
2536 #net_nfvo['description']= net['name']
2537 net_nfvo
['vim_net_id'] = net
['id']
2538 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2539 net_nfvo
['shared'] = net
['shared']
2540 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2542 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2543 net_nfvo
["status"] = "OK"
2544 net_nfvo
["uuid"] = net_id
2545 except db_base_Exception
as e
:
2549 net_nfvo
["status"] = "FAIL: " + str(e
)
2550 net_list
.append(net_nfvo
)
2553 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2554 #get datacenter info
2555 if utils
.check_valid_uuid(datacenter
):
2556 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2558 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2560 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2562 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2563 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2564 datacenter_id
=vims
.keys()[0]
2565 myvim
=vims
[datacenter_id
]
2568 if utils
.check_valid_uuid(name
):
2569 filter_dict
["id"] = name
2571 filter_dict
["name"] = name
2573 if item
=="networks":
2574 #filter_dict['tenant_id'] = myvim['tenant_id']
2575 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2576 elif item
=="tenants":
2577 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2579 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2580 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
2581 if name
and len(content
)==1:
2582 return {item
[:-1]: content
[0]}
2583 elif name
and len(content
)==0:
2584 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
2587 return {item
: content
}
2588 except vimconn
.vimconnException
as e
:
2589 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
2590 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
2592 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
2593 #get datacenter info
2594 if tenant_id
== "any":
2597 if utils
.check_valid_uuid(datacenter
):
2598 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2600 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2602 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2604 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2605 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2606 datacenter_id
=vims
.keys()[0]
2607 myvim
=vims
[datacenter_id
]
2609 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2610 logger
.debug("vim_action_delete vim response: " + str(content
))
2611 items
= content
.values()[0]
2612 if type(items
)==list and len(items
)==0:
2613 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
2614 elif type(items
)==list and len(items
)>1:
2615 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
2616 else: # it is a dict
2617 item_id
= items
["id"]
2618 item_name
= str(items
.get("name"))
2621 if item
=="networks":
2622 content
= myvim
.delete_network(item_id
)
2623 elif item
=="tenants":
2624 content
= myvim
.delete_tenant(item_id
)
2626 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2627 except vimconn
.vimconnException
as e
:
2628 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
2629 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
2631 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
2633 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2634 #get datacenter info
2635 print "vim_action_create descriptor", descriptor
2636 if tenant_id
== "any":
2639 if utils
.check_valid_uuid(datacenter
):
2640 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_id
=datacenter
)
2642 vims
= get_vim(mydb
, nfvo_tenant
=tenant_id
, datacenter_name
=datacenter
)
2644 raise NfvoException("datacenter '{}' not found".format(datacenter
), HTTP_Not_Found
)
2646 #logger.error("nfvo.datacenter_new_netmap() error. Several datacenters found")
2647 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2648 datacenter_id
=vims
.keys()[0]
2649 myvim
=vims
[datacenter_id
]
2652 if item
=="networks":
2653 net
= descriptor
["network"]
2654 net_name
= net
.pop("name")
2655 net_type
= net
.pop("type", "bridge")
2656 net_public
= net
.pop("shared", False)
2657 net_ipprofile
= net
.pop("ip_profile", None)
2658 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, **net
)
2659 elif item
=="tenants":
2660 tenant
= descriptor
["tenant"]
2661 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2663 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2664 except vimconn
.vimconnException
as e
:
2665 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
2667 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)