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$"
35 from db_base
import HTTP_Unauthorized
, HTTP_Bad_Request
, HTTP_Internal_Server_Error
, HTTP_Not_Found
,\
36 HTTP_Conflict
, HTTP_Method_Not_Allowed
37 import console_proxy_thread
as cli
41 from db_base
import db_base_Exception
44 global vimconn_imported
46 global default_volume_size
47 default_volume_size
= '5' #size in GB
50 vimconn_imported
= {} # dictionary with VIM type as key, loaded module as value
51 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
52 logger
= logging
.getLogger('openmano.nfvo')
54 class NfvoException(Exception):
55 def __init__(self
, message
, http_code
):
56 self
.http_code
= http_code
57 Exception.__init
__(self
, message
)
60 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
61 name
= datacenter_name
[:16]
62 if name
not in vim_threads
["names"]:
63 vim_threads
["names"].append(name
)
65 name
= datatacenter_name
[:16] + "." + tenant_name
[:16]
66 if name
not in vim_threads
["names"]:
67 vim_threads
["names"].append(name
)
69 name
= datacenter_id
+ "-" + tenant_id
70 vim_threads
["names"].append(name
)
74 def start_service(mydb
):
75 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'
76 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
77 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
78 'user','passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
80 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
82 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
84 extra
.update(yaml
.load(vim
["config"]))
85 if vim
.get('dt_config'):
86 extra
.update(yaml
.load(vim
["dt_config"]))
87 if vim
["type"] not in vimconn_imported
:
90 module
= "vimconn_" + vim
["type"]
91 module_info
= imp
.find_module(module
)
92 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
93 vimconn_imported
[vim
["type"]] = vim_conn
94 except (IOError, ImportError) as e
:
95 if module_info
and module_info
[0]:
96 file.close(module_info
[0])
97 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
98 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
102 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
103 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
104 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
105 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
106 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
107 user
=vim
['user'], passwd
=vim
['passwd'],
110 except Exception as e
:
111 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
112 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['vim_tenant_id'], vim
['vim_tenant_name'], vim
['vim_tenant_id'])
113 new_thread
= vim_thread
.vim_thread(myvim
, thread_name
)
115 thread_id
= vim
["datacenter_id"] + "-" + vim
['nfvo_tenant_id']
116 vim_threads
["running"][thread_id
] = new_thread
117 except db_base_Exception
as e
:
118 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
121 for thread_id
,thread
in vim_threads
["running"].items():
122 thread
.insert_task("exit")
123 vim_threads
["deleting"][thread_id
] = thread
124 vim_threads
["running"]={}
126 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
128 return result, content:
129 <0, error_text upon error
130 nb_records, flavor_list on success
133 WHERE_dict
['vnf_id'] = vnf_id
134 if nfvo_tenant
is not None:
135 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
137 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
138 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
139 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
140 #print "get_flavor_list result:", result
141 #print "get_flavor_list content:", content
143 for flavor
in flavors
:
144 flavorList
.append(flavor
['flavor_id'])
147 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
149 return result, content:
150 <0, error_text upon error
151 nb_records, flavor_list on success
154 WHERE_dict
['vnf_id'] = vnf_id
155 if nfvo_tenant
is not None:
156 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
158 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
159 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
162 imageList
.append(image
['image_id'])
165 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
166 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
167 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
168 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
169 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
170 raise exception upon error
173 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
174 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
175 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
176 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
177 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
178 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
179 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
180 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'
181 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
182 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
183 'user','passwd', 'dt.config as dt_config')
185 from_
= 'datacenters as d'
186 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
188 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
191 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
193 extra
.update(yaml
.load(vim
["config"]))
194 if vim
.get('dt_config'):
195 extra
.update(yaml
.load(vim
["dt_config"]))
196 if vim
["type"] not in vimconn_imported
:
199 module
= "vimconn_" + vim
["type"]
200 module_info
= imp
.find_module(module
)
201 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
202 vimconn_imported
[vim
["type"]] = vim_conn
203 except (IOError, ImportError) as e
:
204 if module_info
and module_info
[0]:
205 file.close(module_info
[0])
206 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
207 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
211 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
212 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
213 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
214 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
), tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
215 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
216 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
219 except Exception as e
:
220 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
222 except db_base_Exception
as e
:
223 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
225 def rollback(mydb
, vims
, rollback_list
):
227 #delete things by reverse order
228 for i
in range(len(rollback_list
)-1, -1, -1):
229 item
= rollback_list
[i
]
230 if item
["where"]=="vim":
231 if item
["vim_id"] not in vims
:
233 vim
=vims
[ item
["vim_id"] ]
235 if item
["what"]=="image":
236 vim
.delete_image(item
["uuid"])
237 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
238 elif item
["what"]=="flavor":
239 vim
.delete_flavor(item
["uuid"])
240 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
241 elif item
["what"]=="network":
242 vim
.delete_network(item
["uuid"])
243 elif item
["what"]=="vm":
244 vim
.delete_vminstance(item
["uuid"])
245 except vimconn
.vimconnException
as e
:
246 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
247 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
248 except db_base_Exception
as e
:
249 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
253 if item
["what"]=="image":
254 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
255 elif item
["what"]=="flavor":
256 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
257 except db_base_Exception
as e
:
258 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
259 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
260 if len(undeleted_items
)==0:
261 return True," Rollback successful."
263 return False," Rollback fails to delete: " + str(undeleted_items
)
265 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
267 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
269 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
271 #dataplane interfaces
272 for numa
in vnfc
.get("numas",() ):
273 for interface
in numa
.get("interfaces",()):
274 if interface
["name"] in name_dict
:
276 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
277 vnfc
["name"], interface
["name"]),
279 name_dict
[ interface
["name"] ] = "underlay"
281 for interface
in vnfc
.get("bridge-ifaces",() ):
282 if interface
["name"] in name_dict
:
284 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
285 vnfc
["name"], interface
["name"]),
287 name_dict
[ interface
["name"] ] = "overlay"
288 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
289 # check bood-data info
290 if "boot-data" in vnfc
:
291 # check that user-data is incompatible with users and config-files
292 if (vnfc
["boot-data"].get("users") or vnfc
["boot-data"].get("config-files")) and vnfc
["boot-data"].get("user-data"):
294 "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
297 #check if the info in external_connections matches with the one in the vnfcs
299 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
300 if external_connection
["name"] in name_list
:
302 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
303 external_connection
["name"]),
305 name_list
.append(external_connection
["name"])
306 if external_connection
["VNFC"] not in vnfc_interfaces
:
308 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
309 external_connection
["name"], external_connection
["VNFC"]),
312 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
314 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
315 external_connection
["name"],
316 external_connection
["local_iface_name"]),
319 #check if the info in internal_connections matches with the one in the vnfcs
321 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
322 if internal_connection
["name"] in name_list
:
324 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
325 internal_connection
["name"]),
327 name_list
.append(internal_connection
["name"])
328 #We should check that internal-connections of type "ptp" have only 2 elements
330 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
332 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
333 internal_connection
["name"],
334 'ptp' if vnf_descriptor_version
==1 else 'e-line',
335 'data' if vnf_descriptor_version
==1 else "e-lan"),
337 for port
in internal_connection
["elements"]:
339 iface
= port
["local_iface_name"]
340 if vnf
not in vnfc_interfaces
:
342 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
343 internal_connection
["name"], vnf
),
345 if iface
not in vnfc_interfaces
[ vnf
]:
347 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
348 internal_connection
["name"], iface
),
350 return -HTTP_Bad_Request
,
351 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
352 if vnfc_interfaces
[vnf
][iface
] == "overlay":
353 internal_connection
["type"] = "bridge"
355 internal_connection
["type"] = "data"
356 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
357 if vnfc_interfaces
[vnf
][iface
] == "overlay":
358 internal_connection
["implementation"] = "overlay"
360 internal_connection
["implementation"] = "underlay"
361 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
362 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
364 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
365 internal_connection
["name"],
366 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
367 'data' if vnf_descriptor_version
==1 else 'underlay'),
369 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
370 vnfc_interfaces
[vnf
][iface
] == "underlay":
372 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
373 internal_connection
["name"], iface
,
374 'data' if vnf_descriptor_version
==1 else 'underlay',
375 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
379 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
381 if only_create_at_vim
:
382 image_mano_id
= image_dict
['uuid']
383 if return_on_error
== None:
384 return_on_error
= True
386 if image_dict
['location']:
387 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
389 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
391 image_mano_id
= images
[0]['uuid']
393 #create image in MANO DB
394 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
395 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
396 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
398 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
399 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
400 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
401 #create image at every vim
402 for vim_id
,vim
in vims
.iteritems():
403 image_created
="false"
405 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
406 #look at VIM if this image exist
408 if image_dict
['location'] is not None:
409 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
412 filter_dict
['name'] = image_dict
['universal_name']
413 if image_dict
.get('checksum') != None:
414 filter_dict
['checksum'] = image_dict
['checksum']
415 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
416 vim_images
= vim
.get_image_list(filter_dict
)
417 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
418 if len(vim_images
) > 1:
419 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), HTTP_Conflict
)
420 elif len(vim_images
) == 0:
421 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
423 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
424 image_vim_id
= vim_images
[0]['id']
426 except vimconn
.vimconnNotFoundException
as e
:
427 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
429 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
430 if image_dict
['location']:
431 image_vim_id
= vim
.new_image(image_dict
)
432 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
435 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
436 raise vimconn
.vimconnException(str(e
))
437 except vimconn
.vimconnException
as e
:
439 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
442 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
444 except vimconn
.vimconnException
as e
:
446 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
448 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
451 #if we reach here, the image has been created or existed
453 #add new vim_id at datacenters_images
454 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
455 elif image_db
[0]["vim_id"]!=image_vim_id
:
456 #modify existing vim_id at datacenters_images
457 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
459 return image_vim_id
if only_create_at_vim
else image_mano_id
461 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
462 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
463 'ram':flavor_dict
.get('ram'),
464 'vcpus':flavor_dict
.get('vcpus'),
466 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
467 del flavor_dict
['extended']
468 if 'extended' in flavor_dict
:
469 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
471 #look if flavor exist
472 if only_create_at_vim
:
473 flavor_mano_id
= flavor_dict
['uuid']
474 if return_on_error
== None:
475 return_on_error
= True
477 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
479 flavor_mano_id
= flavors
[0]['uuid']
482 #create one by one the images of aditional disks
483 dev_image_list
=[] #list of images
484 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
486 for device
in flavor_dict
['extended'].get('devices',[]):
487 if "image" not in device
and "image name" not in device
:
490 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
491 image_dict
['universal_name']=device
.get('image name')
492 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
493 image_dict
['location']=device
.get('image')
494 #image_dict['new_location']=vnfc.get('image location')
495 image_dict
['checksum']=device
.get('image checksum')
496 image_metadata_dict
= device
.get('image metadata', None)
497 image_metadata_str
= None
498 if image_metadata_dict
!= None:
499 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
500 image_dict
['metadata']=image_metadata_str
501 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
502 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
503 dev_image_list
.append(image_id
)
505 temp_flavor_dict
['name'] = flavor_dict
['name']
506 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
507 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
508 flavor_mano_id
= content
509 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
510 #create flavor at every vim
511 if 'uuid' in flavor_dict
:
512 del flavor_dict
['uuid']
514 for vim_id
,vim
in vims
.items():
515 flavor_created
="false"
517 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
518 #look at VIM if this flavor exist SKIPPED
519 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
521 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
525 #Create the flavor in VIM
526 #Translate images at devices from MANO id to VIM id
528 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
529 #make a copy of original devices
532 for device
in flavor_dict
["extended"].get("devices",[]):
535 devices_original
.append(dev
)
536 if 'image' in device
:
538 if 'image metadata' in device
:
539 del device
['image metadata']
541 for index
in range(0,len(devices_original
)) :
542 device
=devices_original
[index
]
543 if "image" not in device
and "image name" not in device
:
545 disk_list
.append({'size': device
.get('size', default_volume_size
)})
548 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
549 image_dict
['universal_name']=device
.get('image name')
550 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
551 image_dict
['location']=device
.get('image')
552 #image_dict['new_location']=device.get('image location')
553 image_dict
['checksum']=device
.get('image checksum')
554 image_metadata_dict
= device
.get('image metadata', None)
555 image_metadata_str
= None
556 if image_metadata_dict
!= None:
557 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
558 image_dict
['metadata']=image_metadata_str
559 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
560 image_dict
["uuid"]=image_mano_id
561 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
563 #save disk information (image must be based on and size
564 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
566 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
569 #check that this vim_id exist in VIM, if not create
570 flavor_vim_id
=flavor_db
[0]["vim_id"]
572 vim
.get_flavor(flavor_vim_id
)
573 continue #flavor exist
574 except vimconn
.vimconnException
:
576 #create flavor at vim
577 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
580 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
581 flavor_create
="false"
582 except vimconn
.vimconnException
as e
:
585 if not flavor_vim_id
:
586 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
587 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
588 flavor_created
="true"
589 except vimconn
.vimconnException
as e
:
591 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
593 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
596 #if reach here the flavor has been create or exist
597 if len(flavor_db
)==0:
598 #add new vim_id at datacenters_flavors
599 extended_devices_yaml
= None
600 if len(disk_list
) > 0:
601 extended_devices
= dict()
602 extended_devices
['disks'] = disk_list
603 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
604 mydb
.new_row('datacenters_flavors',
605 {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
,
606 'created':flavor_created
,'extended': extended_devices_yaml
})
607 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
608 #modify existing vim_id at datacenters_flavors
609 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
611 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
613 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
616 # Step 1. Check the VNF descriptor
617 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
618 # Step 2. Check tenant exist
620 if tenant_id
!= "any":
621 check_tenant(mydb
, tenant_id
)
622 if "tenant_id" in vnf_descriptor
["vnf"]:
623 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
624 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
627 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
628 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
629 if global_config
["auto_push_VNF_to_VIMs"]:
630 vims
= get_vim(mydb
, tenant_id
)
632 # Step 4. Review the descriptor and add missing fields
633 #print vnf_descriptor
634 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
635 vnf_name
= vnf_descriptor
['vnf']['name']
636 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
637 if "physical" in vnf_descriptor
['vnf']:
638 del vnf_descriptor
['vnf']['physical']
639 #print vnf_descriptor
641 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
642 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
643 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
645 #For each VNFC, we add it to the VNFCDict and we create a flavor.
646 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
647 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
649 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
650 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
652 VNFCitem
["name"] = vnfc
['name']
653 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
655 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
658 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
659 myflavorDict
["description"] = VNFCitem
["description"]
660 myflavorDict
["ram"] = vnfc
.get("ram", 0)
661 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
662 myflavorDict
["disk"] = vnfc
.get("disk", 1)
663 myflavorDict
["extended"] = {}
665 devices
= vnfc
.get("devices")
667 myflavorDict
["extended"]["devices"] = devices
670 # 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
671 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
673 # Previous code has been commented
674 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
675 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
676 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
677 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
679 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
681 # print "Error creating flavor: unknown processor model. Rollback successful."
682 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
684 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
685 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
687 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
688 myflavorDict
['extended']['numas'] = vnfc
['numas']
692 # Step 6.2 New flavors are created in the VIM
693 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
695 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
696 VNFCitem
["flavor_id"] = flavor_id
697 VNFCDict
[vnfc
['name']] = VNFCitem
699 logger
.debug("Creating new images in the VIM for each VNFC")
700 # Step 6.3 New images are created in the VIM
701 #For each VNFC, we must create the appropriate image.
702 #This "for" loop might be integrated with the previous one
703 #In case this integration is made, the VNFCDict might become a VNFClist.
704 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
705 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
707 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
708 image_dict
['universal_name']=vnfc
.get('image name')
709 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
710 image_dict
['location']=vnfc
.get('VNFC image')
711 #image_dict['new_location']=vnfc.get('image location')
712 image_dict
['checksum']=vnfc
.get('image checksum')
713 image_metadata_dict
= vnfc
.get('image metadata', None)
714 image_metadata_str
= None
715 if image_metadata_dict
is not None:
716 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
717 image_dict
['metadata']=image_metadata_str
718 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
719 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
720 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
721 VNFCDict
[vnfc
['name']]["image_id"] = image_id
722 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
723 if vnfc
.get("boot-data"):
724 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
727 # Step 7. Storing the VNF descriptor in the repository
728 if "descriptor" not in vnf_descriptor
["vnf"]:
729 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
731 # Step 8. Adding the VNF to the NFVO DB
732 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
734 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
735 _
, message
= rollback(mydb
, vims
, rollback_list
)
736 if isinstance(e
, db_base_Exception
):
737 error_text
= "Exception at database"
738 elif isinstance(e
, KeyError):
739 error_text
= "KeyError exception "
740 e
.http_code
= HTTP_Internal_Server_Error
742 error_text
= "Exception at VIM"
743 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
744 #logger.error("start_scenario %s", error_text)
745 raise NfvoException(error_text
, e
.http_code
)
747 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
750 # Step 1. Check the VNF descriptor
751 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
752 # Step 2. Check tenant exist
754 if tenant_id
!= "any":
755 check_tenant(mydb
, tenant_id
)
756 if "tenant_id" in vnf_descriptor
["vnf"]:
757 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
758 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
761 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
762 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
763 if global_config
["auto_push_VNF_to_VIMs"]:
764 vims
= get_vim(mydb
, tenant_id
)
766 # Step 4. Review the descriptor and add missing fields
767 #print vnf_descriptor
768 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
769 vnf_name
= vnf_descriptor
['vnf']['name']
770 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
771 if "physical" in vnf_descriptor
['vnf']:
772 del vnf_descriptor
['vnf']['physical']
773 #print vnf_descriptor
775 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
776 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
777 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
779 #For each VNFC, we add it to the VNFCDict and we create a flavor.
780 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
781 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
783 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
784 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
786 VNFCitem
["name"] = vnfc
['name']
787 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
789 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
792 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
793 myflavorDict
["description"] = VNFCitem
["description"]
794 myflavorDict
["ram"] = vnfc
.get("ram", 0)
795 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
796 myflavorDict
["disk"] = vnfc
.get("disk", 1)
797 myflavorDict
["extended"] = {}
799 devices
= vnfc
.get("devices")
801 myflavorDict
["extended"]["devices"] = devices
804 # 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
805 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
807 # Previous code has been commented
808 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
809 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
810 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
811 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
813 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
815 # print "Error creating flavor: unknown processor model. Rollback successful."
816 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
818 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
819 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
821 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
822 myflavorDict
['extended']['numas'] = vnfc
['numas']
826 # Step 6.2 New flavors are created in the VIM
827 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
829 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
830 VNFCitem
["flavor_id"] = flavor_id
831 VNFCDict
[vnfc
['name']] = VNFCitem
833 logger
.debug("Creating new images in the VIM for each VNFC")
834 # Step 6.3 New images are created in the VIM
835 #For each VNFC, we must create the appropriate image.
836 #This "for" loop might be integrated with the previous one
837 #In case this integration is made, the VNFCDict might become a VNFClist.
838 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
839 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
841 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
842 image_dict
['universal_name']=vnfc
.get('image name')
843 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
844 image_dict
['location']=vnfc
.get('VNFC image')
845 #image_dict['new_location']=vnfc.get('image location')
846 image_dict
['checksum']=vnfc
.get('image checksum')
847 image_metadata_dict
= vnfc
.get('image metadata', None)
848 image_metadata_str
= None
849 if image_metadata_dict
is not None:
850 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
851 image_dict
['metadata']=image_metadata_str
852 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
853 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
854 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
855 VNFCDict
[vnfc
['name']]["image_id"] = image_id
856 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
857 if vnfc
.get("boot-data"):
858 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
860 # Step 7. Storing the VNF descriptor in the repository
861 if "descriptor" not in vnf_descriptor
["vnf"]:
862 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
864 # Step 8. Adding the VNF to the NFVO DB
865 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
867 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
868 _
, message
= rollback(mydb
, vims
, rollback_list
)
869 if isinstance(e
, db_base_Exception
):
870 error_text
= "Exception at database"
871 elif isinstance(e
, KeyError):
872 error_text
= "KeyError exception "
873 e
.http_code
= HTTP_Internal_Server_Error
875 error_text
= "Exception at VIM"
876 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
877 #logger.error("start_scenario %s", error_text)
878 raise NfvoException(error_text
, e
.http_code
)
880 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
881 #check valid tenant_id
882 check_tenant(mydb
, tenant_id
)
885 if tenant_id
!= "any":
886 where_or
["tenant_id"] = tenant_id
887 where_or
["public"] = True
888 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
891 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
892 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
893 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
894 data
={'vnf' : filtered_content
}
896 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
897 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description', 'boot_data'),
898 WHERE
={'vnfs.uuid': vnf_id
} )
900 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
901 # change boot_data into boot-data
903 if vm
.get("boot_data"):
904 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
907 data
['vnf']['VNFC'] = content
908 #TODO: GET all the information from a VNFC and include it in the output.
911 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
912 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
913 WHERE
={'vnfs.uuid': vnf_id
} )
914 data
['vnf']['nets'] = content
916 #GET ip-profile for each net
917 for net
in data
['vnf']['nets']:
918 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
919 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
920 WHERE
={'net_id': net
["uuid"]} )
921 if len(ipprofiles
)==1:
922 net
["ip_profile"] = ipprofiles
[0]
923 elif len(ipprofiles
)>1:
924 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
927 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
929 #GET External Interfaces
930 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
931 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
932 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
933 WHERE
={'vnfs.uuid': vnf_id
},
934 WHERE_NOT
={'interfaces.external_name': None} )
936 data
['vnf']['external-connections'] = content
941 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
943 if tenant_id
!= "any":
944 check_tenant(mydb
, tenant_id
)
945 # Get the URL of the VIM from the nfvo_tenant and the datacenter
946 vims
= get_vim(mydb
, tenant_id
)
950 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
952 if tenant_id
!= "any":
953 where_or
["tenant_id"] = tenant_id
954 where_or
["public"] = True
955 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
958 # "Getting the list of flavors and tenants of the VNF"
959 flavorList
= get_flavorlist(mydb
, vnf_id
)
960 if len(flavorList
)==0:
961 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
963 imageList
= get_imagelist(mydb
, vnf_id
)
964 if len(imageList
)==0:
965 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
967 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
969 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
972 for flavor
in flavorList
:
973 #check if flavor is used by other vnf
975 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
977 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
979 #flavor not used, must be deleted
981 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
983 if flavor_vim
["datacenter_id"] not in vims
:
985 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
987 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
989 myvim
.delete_flavor(flavor_vim
["vim_id"])
990 except vimconn
.vimconnNotFoundException
as e
:
991 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
992 except vimconn
.vimconnException
as e
:
993 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
994 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
995 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
996 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
997 mydb
.delete_row_by_id('flavors', flavor
)
998 except db_base_Exception
as e
:
999 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1000 undeletedItems
.append("flavor %s" % flavor
)
1003 for image
in imageList
:
1005 #check if image is used by other vnf
1006 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1008 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1010 #image not used, must be deleted
1012 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1014 if image_vim
["datacenter_id"] not in vims
:
1016 if image_vim
['created']=='false': #skip this image because not created by openmano
1018 myvim
=vims
[ image_vim
["datacenter_id"] ]
1020 myvim
.delete_image(image_vim
["vim_id"])
1021 except vimconn
.vimconnNotFoundException
as e
:
1022 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1023 except vimconn
.vimconnException
as e
:
1024 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1025 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1026 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1027 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1028 mydb
.delete_row_by_id('images', image
)
1029 except db_base_Exception
as e
:
1030 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1031 undeletedItems
.append("image %s" % image
)
1033 return vnf_id
+ " " + vnf
["name"]
1035 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1037 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1038 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1042 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1043 myvim
= vims
.values()[0]
1044 result
,servers
= myvim
.get_hosts_info()
1046 return result
, servers
1047 topology
= {'name':myvim
['name'] , 'servers': servers
}
1048 return result
, topology
1050 def get_hosts(mydb
, nfvo_tenant_id
):
1051 vims
= get_vim(mydb
, nfvo_tenant_id
)
1053 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1055 #print "nfvo.datacenter_action() error. Several datacenters found"
1056 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1057 myvim
= vims
.values()[0]
1059 hosts
= myvim
.get_hosts()
1060 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1062 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1064 server
={'name':host
['name'], 'vms':[]}
1065 for vm
in host
['instances']:
1066 #get internal name and model
1068 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1069 WHERE
={'vim_vm_id':vm
['id']} )
1071 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1073 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1075 except db_base_Exception
as e
:
1076 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1077 datacenter
['Datacenters'][0]['servers'].append(server
)
1078 #return -400, "en construccion"
1080 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1082 except vimconn
.vimconnException
as e
:
1083 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1085 def new_scenario(mydb
, tenant_id
, topo
):
1087 # result, vims = get_vim(mydb, tenant_id)
1089 # return result, vims
1091 if tenant_id
!= "any":
1092 check_tenant(mydb
, tenant_id
)
1093 if "tenant_id" in topo
:
1094 if topo
["tenant_id"] != tenant_id
:
1095 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1100 #1.1: get VNFs and external_networks (other_nets).
1102 other_nets
={} #external_networks, bridge_networks and data_networkds
1103 nodes
= topo
['topology']['nodes']
1104 for k
in nodes
.keys():
1105 if nodes
[k
]['type'] == 'VNF':
1107 vnfs
[k
]['ifaces'] = {}
1108 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1109 other_nets
[k
] = nodes
[k
]
1110 other_nets
[k
]['external']=True
1111 elif nodes
[k
]['type'] == 'network':
1112 other_nets
[k
] = nodes
[k
]
1113 other_nets
[k
]['external']=False
1116 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1117 for name
,vnf
in vnfs
.items():
1119 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1121 error_pos
= "'topology':'nodes':'" + name
+ "'"
1123 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1124 where
['uuid'] = vnf
['vnf_id']
1125 if 'VNF model' in vnf
:
1126 error_text
+= " 'VNF model' " + vnf
['VNF model']
1127 where
['name'] = vnf
['VNF model']
1129 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1131 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1137 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1139 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1140 vnf
['uuid']=vnf_db
[0]['uuid']
1141 vnf
['description']=vnf_db
[0]['description']
1142 #get external interfaces
1143 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1144 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1145 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1146 for ext_iface
in ext_ifaces
:
1147 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1149 #1.4 get list of connections
1150 conections
= topo
['topology']['connections']
1151 conections_list
= []
1152 conections_list_name
= []
1153 for k
in conections
.keys():
1154 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1155 ifaces_list
= conections
[k
]['nodes'].items()
1156 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1158 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1159 for k2
in conection_pair_list
:
1162 con_type
= conections
[k
].get("type", "link")
1163 if con_type
!= "link":
1165 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1166 other_nets
[k
] = {'external': False}
1167 if conections
[k
].get("graph"):
1168 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1169 ifaces_list
.append( (k
, None) )
1172 if con_type
== "external_network":
1173 other_nets
[k
]['external'] = True
1174 if conections
[k
].get("model"):
1175 other_nets
[k
]["model"] = conections
[k
]["model"]
1177 other_nets
[k
]["model"] = k
1178 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1179 other_nets
[k
]["model"] = con_type
1181 conections_list_name
.append(k
)
1182 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)
1183 #print set(ifaces_list)
1184 #check valid VNF and iface names
1185 for iface
in ifaces_list
:
1186 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1187 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1188 str(k
), iface
[0]), HTTP_Not_Found
)
1189 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1190 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1191 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1193 #1.5 unify connections from the pair list to a consolidated list
1195 while index
< len(conections_list
):
1197 while index2
< len(conections_list
):
1198 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1199 conections_list
[index
] |
= conections_list
[index2
]
1200 del conections_list
[index2
]
1201 del conections_list_name
[index2
]
1204 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1206 #for k in conections_list:
1211 #1.6 Delete non external nets
1212 # for k in other_nets.keys():
1213 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1214 # for con in conections_list:
1216 # for index in range(0,len(con)):
1217 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1218 # for index in delete_indexes:
1221 #1.7: Check external_ports are present at database table datacenter_nets
1222 for k
,net
in other_nets
.items():
1223 error_pos
= "'topology':'nodes':'" + k
+ "'"
1224 if net
['external']==False:
1225 if 'name' not in net
:
1227 if 'model' not in net
:
1228 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1229 if net
['model']=='bridge_net':
1230 net
['type']='bridge';
1231 elif net
['model']=='dataplane_net':
1234 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1236 #IF we do not want to check that external network exist at datacenter
1241 # if 'net_id' in net:
1242 # error_text += " 'net_id' " + net['net_id']
1243 # WHERE_['uuid'] = net['net_id']
1244 # if 'model' in net:
1245 # error_text += " 'model' " + net['model']
1246 # WHERE_['name'] = net['model']
1247 # if len(WHERE_) == 0:
1248 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1249 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1250 # FROM='datacenter_nets', WHERE=WHERE_ )
1252 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1254 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1255 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1257 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1258 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1259 # other_nets[k].update(net_db[0])
1262 net_nb
=0 #Number of nets
1263 for con
in conections_list
:
1264 #check if this is connected to a external net
1268 for index
in range(0,len(con
)):
1269 #check if this is connected to a external net
1270 for net_key
in other_nets
.keys():
1271 if con
[index
][0]==net_key
:
1272 if other_net_index
>=0:
1273 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1274 #print "nfvo.new_scenario " + error_text
1275 raise NfvoException(error_text
, HTTP_Bad_Request
)
1277 other_net_index
= index
1278 net_target
= net_key
1280 #print "other_net_index", other_net_index
1282 if other_net_index
>=0:
1283 del con
[other_net_index
]
1284 #IF we do not want to check that external network exist at datacenter
1285 if other_nets
[net_target
]['external'] :
1286 if "name" not in other_nets
[net_target
]:
1287 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1288 if other_nets
[net_target
]["type"] == "external_network":
1289 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1290 other_nets
[net_target
]["type"] = "data"
1292 other_nets
[net_target
]["type"] = "bridge"
1294 # if other_nets[net_target]['external'] :
1295 # 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
1296 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1297 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1298 # print "nfvo.new_scenario " + error_text
1299 # return -HTTP_Bad_Request, error_text
1302 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1305 net_type_bridge
=False
1307 net_target
= "__-__net"+str(net_nb
)
1308 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1309 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1312 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1313 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1314 if iface_type
=='mgmt' or iface_type
=='bridge':
1315 net_type_bridge
= True
1317 net_type_data
= True
1318 if net_type_bridge
and net_type_data
:
1319 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1320 #print "nfvo.new_scenario " + error_text
1321 raise NfvoException(error_text
, HTTP_Bad_Request
)
1322 elif net_type_bridge
:
1325 type_
='data' if len(con
)>2 else 'ptp'
1326 net_list
[net_target
]['type'] = type_
1329 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1330 #print "nfvo.new_scenario " + error_text
1332 raise NfvoException(error_text
, HTTP_Bad_Request
)
1334 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1335 #1.8.1 obtain management net
1336 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1337 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1338 #1.8.2 check all interfaces from all vnfs
1340 add_mgmt_net
= False
1341 for vnf
in vnfs
.values():
1342 for iface
in vnf
['ifaces'].values():
1343 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1344 #iface not connected
1345 iface
['net_key'] = 'mgmt'
1347 if add_mgmt_net
and 'mgmt' not in net_list
:
1348 net_list
['mgmt']=mgmt_net
[0]
1349 net_list
['mgmt']['external']=True
1350 net_list
['mgmt']['graph']={'visible':False}
1352 net_list
.update(other_nets
)
1354 #print 'net_list', net_list
1359 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1360 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1361 'tenant_id':tenant_id
, 'name':topo
['name'],
1362 'description':topo
.get('description',topo
['name']),
1363 'public': topo
.get('public', False)
1368 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
):
1369 scenario
= scenario_dict
["scenario"]
1370 if tenant_id
!= "any":
1371 check_tenant(mydb
, tenant_id
)
1372 if "tenant_id" in scenario
:
1373 if scenario
["tenant_id"] != tenant_id
:
1374 print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1375 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1376 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1380 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1381 for name
,vnf
in scenario
["vnfs"].iteritems():
1383 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1385 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1387 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1388 where
['uuid'] = vnf
['vnf_id']
1389 if 'vnf_name' in vnf
:
1390 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1391 where
['name'] = vnf
['vnf_name']
1393 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1394 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1400 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1402 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1403 vnf
['uuid']=vnf_db
[0]['uuid']
1404 vnf
['description']=vnf_db
[0]['description']
1406 #get external interfaces
1407 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1408 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1409 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1410 for ext_iface
in ext_ifaces
:
1411 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1413 #2: Insert net_key at every vnf interface
1414 for net_name
,net
in scenario
["networks"].iteritems():
1415 net_type_bridge
=False
1417 for iface_dict
in net
["interfaces"]:
1418 for vnf
,iface
in iface_dict
.iteritems():
1419 if vnf
not in scenario
["vnfs"]:
1420 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1421 #print "nfvo.new_scenario_v02 " + error_text
1422 raise NfvoException(error_text
, HTTP_Not_Found
)
1423 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1424 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1425 #print "nfvo.new_scenario_v02 " + error_text
1426 raise NfvoException(error_text
, HTTP_Bad_Request
)
1427 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1428 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1429 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1430 #print "nfvo.new_scenario_v02 " + error_text
1431 raise NfvoException(error_text
, HTTP_Bad_Request
)
1432 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1433 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1434 if iface_type
=='mgmt' or iface_type
=='bridge':
1435 net_type_bridge
= True
1437 net_type_data
= True
1438 if net_type_bridge
and net_type_data
:
1439 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1440 #print "nfvo.new_scenario " + error_text
1441 raise NfvoException(error_text
, HTTP_Bad_Request
)
1442 elif net_type_bridge
:
1445 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1447 net
['name'] = net_name
1448 net
['external'] = net
.get('external', False)
1450 #3: insert at database
1451 scenario
["nets"] = scenario
["networks"]
1452 scenario
['tenant_id'] = tenant_id
1453 scenario_id
= mydb
.new_scenario( scenario
)
1456 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1457 data
["uuid"] = scenario_id
1458 data
["tenant_id"] = tenant_id
1459 c
= mydb
.edit_scenario( data
)
1462 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1463 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1464 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
1465 vims
= {datacenter_id
: myvim
}
1466 myvim_tenant
= myvim
['tenant_id']
1467 datacenter_name
= myvim
['name']
1471 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1472 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1473 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
1474 scenarioDict
['datacenter_id'] = datacenter_id
1475 #print '================scenarioDict======================='
1476 #print json.dumps(scenarioDict, indent=4)
1477 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1479 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1480 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1482 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1483 auxNetDict
['scenario'] = {}
1485 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1486 for sce_net
in scenarioDict
['nets']:
1487 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1489 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1490 myNetName
= myNetName
[0:255] #limit length
1491 myNetType
= sce_net
['type']
1493 myNetDict
["name"] = myNetName
1494 myNetDict
["type"] = myNetType
1495 myNetDict
["tenant_id"] = myvim_tenant
1496 myNetIPProfile
= sce_net
.get('ip_profile', None)
1498 #We should use the dictionary as input parameter for new_network
1500 if not sce_net
["external"]:
1501 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1502 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1503 sce_net
['vim_id'] = network_id
1504 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1505 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1506 sce_net
["created"] = True
1508 if sce_net
['vim_id'] == None:
1509 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1510 _
, message
= rollback(mydb
, vims
, rollbackList
)
1511 logger
.error("nfvo.start_scenario: %s", error_text
)
1512 raise NfvoException(error_text
, HTTP_Bad_Request
)
1513 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1514 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1516 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1517 #For each vnf net, we create it and we add it to instanceNetlist.
1518 for sce_vnf
in scenarioDict
['vnfs']:
1519 for net
in sce_vnf
['nets']:
1520 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1522 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1523 myNetName
= myNetName
[0:255] #limit length
1524 myNetType
= net
['type']
1526 myNetDict
["name"] = myNetName
1527 myNetDict
["type"] = myNetType
1528 myNetDict
["tenant_id"] = myvim_tenant
1529 myNetIPProfile
= net
.get('ip_profile', None)
1532 #We should use the dictionary as input parameter for new_network
1533 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1534 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1535 net
['vim_id'] = network_id
1536 if sce_vnf
['uuid'] not in auxNetDict
:
1537 auxNetDict
[sce_vnf
['uuid']] = {}
1538 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1539 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1540 net
["created"] = True
1542 #print "auxNetDict:"
1543 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1545 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1546 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1548 for sce_vnf
in scenarioDict
['vnfs']:
1549 for vm
in sce_vnf
['vms']:
1552 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1553 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
1554 #myVMDict['description'] = vm['description']
1555 myVMDict
['description'] = myVMDict
['name'][0:99]
1557 myVMDict
['start'] = "no"
1558 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1559 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1561 #create image at vim in case it not exist
1562 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1563 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1564 vm
['vim_image_id'] = image_id
1566 #create flavor at vim in case it not exist
1567 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1568 if flavor_dict
['extended']!=None:
1569 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1570 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1571 vm
['vim_flavor_id'] = flavor_id
1574 myVMDict
['imageRef'] = vm
['vim_image_id']
1575 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1576 myVMDict
['networks'] = []
1577 for iface
in vm
['interfaces']:
1579 if iface
['type']=="data":
1580 netDict
['type'] = iface
['model']
1581 elif "model" in iface
and iface
["model"]!=None:
1582 netDict
['model']=iface
['model']
1583 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1584 #discover type of interface looking at flavor
1585 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1586 for flavor_iface
in numa
.get('interfaces',[]):
1587 if flavor_iface
.get('name') == iface
['internal_name']:
1588 if flavor_iface
['dedicated'] == 'yes':
1589 netDict
['type']="PF" #passthrough
1590 elif flavor_iface
['dedicated'] == 'no':
1591 netDict
['type']="VF" #siov
1592 elif flavor_iface
['dedicated'] == 'yes:sriov':
1593 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1594 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1596 netDict
["use"]=iface
['type']
1597 if netDict
["use"]=="data" and not netDict
.get("type"):
1598 #print "netDict", netDict
1599 #print "iface", iface
1600 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'])
1601 if flavor_dict
.get('extended')==None:
1602 raise NfvoException(e_text
+ "After database migration some information is not available. \
1603 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1605 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1606 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1607 netDict
["type"]="virtual"
1608 if "vpci" in iface
and iface
["vpci"] is not None:
1609 netDict
['vpci'] = iface
['vpci']
1610 if "mac" in iface
and iface
["mac"] is not None:
1611 netDict
['mac_address'] = iface
['mac']
1612 if "port-security" in iface
and iface
["port-security"] is not None:
1613 netDict
['port_security'] = iface
['port-security']
1614 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
1615 netDict
['floating_ip'] = iface
['floating-ip']
1616 netDict
['name'] = iface
['internal_name']
1617 if iface
['net_id'] is None:
1618 for vnf_iface
in sce_vnf
["interfaces"]:
1621 if vnf_iface
['interface_id']==iface
['uuid']:
1622 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1625 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1626 #skip bridge ifaces not connected to any net
1627 #if 'net_id' not in netDict or netDict['net_id']==None:
1629 myVMDict
['networks'].append(netDict
)
1630 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1631 #print myVMDict['name']
1632 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1633 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1634 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1635 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1636 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1637 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1638 vm
['vim_id'] = vm_id
1639 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1640 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1641 for net
in myVMDict
['networks']:
1643 for iface
in vm
['interfaces']:
1644 if net
["name"]==iface
["internal_name"]:
1645 iface
["vim_id"]=net
["vim_id"]
1648 logger
.debug("start scenario Deployment done")
1649 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1650 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1651 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1652 return mydb
.get_instance_scenario(instance_id
)
1654 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1655 _
, message
= rollback(mydb
, vims
, rollbackList
)
1656 if isinstance(e
, db_base_Exception
):
1657 error_text
= "Exception at database"
1659 error_text
= "Exception at VIM"
1660 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1661 #logger.error("start_scenario %s", error_text)
1662 raise NfvoException(error_text
, e
.http_code
)
1664 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
1665 ''' join the cloud config information into cloud_config_preserve.
1666 In case of conflict cloud_config_preserve preserves
1669 if not cloud_config_preserve
and not cloud_config
:
1672 new_cloud_config
= {"key-pairs":[], "users":[]}
1674 if cloud_config_preserve
:
1675 for key
in cloud_config_preserve
.get("key-pairs", () ):
1676 if key
not in new_cloud_config
["key-pairs"]:
1677 new_cloud_config
["key-pairs"].append(key
)
1679 for key
in cloud_config
.get("key-pairs", () ):
1680 if key
not in new_cloud_config
["key-pairs"]:
1681 new_cloud_config
["key-pairs"].append(key
)
1682 if not new_cloud_config
["key-pairs"]:
1683 del new_cloud_config
["key-pairs"]
1687 new_cloud_config
["users"] += cloud_config
.get("users", () )
1688 if cloud_config_preserve
:
1689 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
1690 index_to_delete
= []
1691 users
= new_cloud_config
.get("users", [])
1692 for index0
in range(0,len(users
)):
1693 if index0
in index_to_delete
:
1695 for index1
in range(index0
+1,len(users
)):
1696 if index1
in index_to_delete
:
1698 if users
[index0
]["name"] == users
[index1
]["name"]:
1699 index_to_delete
.append(index1
)
1700 for key
in users
[index1
].get("key-pairs",()):
1701 if "key-pairs" not in users
[index0
]:
1702 users
[index0
]["key-pairs"] = [key
]
1703 elif key
not in users
[index0
]["key-pairs"]:
1704 users
[index0
]["key-pairs"].append(key
)
1705 index_to_delete
.sort(reverse
=True)
1706 for index
in index_to_delete
:
1708 if not new_cloud_config
["users"]:
1709 del new_cloud_config
["users"]
1712 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
1713 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
1714 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
1715 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
1718 if cloud_config
and cloud_config
.get("user-data") != None:
1719 new_cloud_config
["user-data"] = cloud_config
["user-data"]
1720 if cloud_config_preserve
and cloud_config_preserve
.get("user-data") != None:
1721 new_cloud_config
["user-data"] = cloud_config_preserve
["user-data"]
1724 new_cloud_config
["config-files"] = []
1725 if cloud_config
and cloud_config
.get("config-files") != None:
1726 new_cloud_config
["config-files"] += cloud_config
["config-files"]
1727 if cloud_config_preserve
:
1728 for file in cloud_config_preserve
.get("config-files", ()):
1729 for index
in range(0, len(new_cloud_config
["config-files"])):
1730 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
1731 new_cloud_config
["config-files"][index
] = file
1734 new_cloud_config
["config-files"].append(file)
1735 if not new_cloud_config
["config-files"]:
1736 del new_cloud_config
["config-files"]
1737 return new_cloud_config
1741 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1742 datacenter_id
= None
1743 datacenter_name
= None
1744 if datacenter_id_name
:
1745 if utils
.check_valid_uuid(datacenter_id_name
):
1746 datacenter_id
= datacenter_id_name
1748 datacenter_name
= datacenter_id_name
1749 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1751 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1753 #print "nfvo.datacenter_action() error. Several datacenters found"
1754 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1755 return vims
.keys()[0], vims
.values()[0]
1757 def new_scenario_v03(mydb
, tenant_id
, scenario_dict
):
1758 scenario
= scenario_dict
["scenario"]
1759 if tenant_id
!= "any":
1760 check_tenant(mydb
, tenant_id
)
1761 if "tenant_id" in scenario
:
1762 if scenario
["tenant_id"] != tenant_id
:
1763 logger("Tenant '%s' not found", tenant_id
)
1764 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1765 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1769 #1: Check that VNF are present at database table vnfs and update content into scenario dict
1770 for name
,vnf
in scenario
["vnfs"].iteritems():
1772 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1774 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1776 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1777 where
['uuid'] = vnf
['vnf_id']
1778 if 'vnf_name' in vnf
:
1779 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1780 where
['name'] = vnf
['vnf_name']
1782 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1783 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1789 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1791 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1792 vnf
['uuid']=vnf_db
[0]['uuid']
1793 vnf
['description']=vnf_db
[0]['description']
1795 # get external interfaces
1796 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1797 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1798 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1799 for ext_iface
in ext_ifaces
:
1800 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1802 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1804 #2: Insert net_key and ip_address at every vnf interface
1805 for net_name
,net
in scenario
["networks"].iteritems():
1806 net_type_bridge
=False
1808 for iface_dict
in net
["interfaces"]:
1809 logger
.debug("Iface_dict %s", iface_dict
)
1810 vnf
= iface_dict
["vnf"]
1811 iface
= iface_dict
["vnf_interface"]
1812 if vnf
not in scenario
["vnfs"]:
1813 error_text
= "Error at 'networks':'%s':'interfaces' VNF '%s' not match any VNF at 'vnfs'" % (net_name
, vnf
)
1814 #logger.debug(error_text)
1815 raise NfvoException(error_text
, HTTP_Not_Found
)
1816 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1817 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface not match any VNF interface" % (net_name
, iface
)
1818 #logger.debug(error_text)
1819 raise NfvoException(error_text
, HTTP_Bad_Request
)
1820 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1821 error_text
= "Error at 'networks':'%s':'interfaces':'%s' interface already connected at network '%s'" \
1822 % (net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1823 #logger.debug(error_text)
1824 raise NfvoException(error_text
, HTTP_Bad_Request
)
1825 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1826 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['ip_address'] = iface_dict
.get('ip_address',None)
1827 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1828 if iface_type
=='mgmt' or iface_type
=='bridge':
1829 net_type_bridge
= True
1831 net_type_data
= True
1832 if net_type_bridge
and net_type_data
:
1833 error_text
= "Error connection interfaces of bridge type and data type at 'networks':'%s':'interfaces'" % (net_name
)
1834 #logger.debug(error_text)
1835 raise NfvoException(error_text
, HTTP_Bad_Request
)
1836 elif net_type_bridge
:
1839 type_
='data' if len(net
["interfaces"])>2 else 'ptp'
1841 if ("implementation" in net
):
1842 if (type_
== "bridge" and net
["implementation"] == "underlay"):
1843 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at 'network':'%s'" % (net_name
)
1844 #logger.debug(error_text)
1845 raise NfvoException(error_text
, HTTP_Bad_Request
)
1846 elif (type_
<> "bridge" and net
["implementation"] == "overlay"):
1847 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at 'network':'%s'" % (net_name
)
1848 #logger.debug(error_text)
1849 raise NfvoException(error_text
, HTTP_Bad_Request
)
1850 net
.pop("implementation")
1852 if (type_
== "data" and net
["type"] == "e-line"):
1853 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type 'e-line' at 'network':'%s'" % (net_name
)
1854 #logger.debug(error_text)
1855 raise NfvoException(error_text
, HTTP_Bad_Request
)
1856 elif (type_
== "ptp" and net
["type"] == "e-lan"):
1860 net
['name'] = net_name
1861 net
['external'] = net
.get('external', False)
1863 #3: insert at database
1864 scenario
["nets"] = scenario
["networks"]
1865 scenario
['tenant_id'] = tenant_id
1866 scenario_id
= mydb
.new_scenario2(scenario
)
1870 '''Takes dict d and updates it with the values in dict u.'''
1871 '''It merges all depth levels'''
1872 for k
, v
in u
.iteritems():
1873 if isinstance(v
, collections
.Mapping
):
1874 r
= update(d
.get(k
, {}), v
)
1880 def create_instance(mydb
, tenant_id
, instance_dict
):
1881 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1882 #logger.debug("Creating instance...")
1883 scenario
= instance_dict
["scenario"]
1885 #find main datacenter
1887 datacenter2tenant
= {}
1888 datacenter
= instance_dict
.get("datacenter")
1889 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1890 myvims
[default_datacenter_id
] = vim
1891 datacenter2tenant
[default_datacenter_id
] = vim
['config']['datacenter_tenant_id']
1892 #myvim_tenant = myvim['tenant_id']
1893 # default_datacenter_name = vim['name']
1896 #print "Checking that the scenario exists and getting the scenario dictionary"
1897 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1899 #logger.debug(">>>>>>> Dictionaries before merging")
1900 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1901 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1903 scenarioDict
['datacenter_id'] = default_datacenter_id
1905 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1906 auxNetDict
['scenario'] = {}
1908 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1909 instance_name
= instance_dict
["name"]
1910 instance_description
= instance_dict
.get("description")
1912 #0 check correct parameters
1913 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1915 for scenario_net
in scenarioDict
['nets']:
1916 if net_name
== scenario_net
["name"]:
1920 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1921 if "sites" not in net_instance_desc
:
1922 net_instance_desc
["sites"] = [ {} ]
1923 site_without_datacenter_field
= False
1924 for site
in net_instance_desc
["sites"]:
1925 if site
.get("datacenter"):
1926 if site
["datacenter"] not in myvims
:
1927 #Add this datacenter to myvims
1928 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1930 datacenter2tenant
[d
] = v
['config']['datacenter_tenant_id']
1931 site
["datacenter"] = d
#change name to id
1933 if site_without_datacenter_field
:
1934 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1935 site_without_datacenter_field
= True
1936 site
["datacenter"] = default_datacenter_id
#change name to id
1938 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
1940 for scenario_vnf
in scenarioDict
['vnfs']:
1941 if vnf_name
== scenario_vnf
['name']:
1945 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
1946 if "datacenter" in vnf_instance_desc
:
1947 #Add this datacenter to myvims
1948 if vnf_instance_desc
["datacenter"] not in myvims
:
1949 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
1951 datacenter2tenant
[d
] = v
['config']['datacenter_tenant_id']
1952 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
1954 #0.1 parse cloud-config parameters
1955 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
1957 #0.2 merge instance information into scenario
1958 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
1959 #However, this is not possible yet.
1960 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1961 for scenario_net
in scenarioDict
['nets']:
1962 if net_name
== scenario_net
["name"]:
1963 if 'ip-profile' in net_instance_desc
:
1964 ipprofile
= net_instance_desc
['ip-profile']
1965 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
1966 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
1967 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
1968 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
1969 if 'dhcp' in ipprofile
:
1970 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
1971 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
1972 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
1973 del ipprofile
['dhcp']
1974 if 'ip_profile' not in scenario_net
:
1975 scenario_net
['ip_profile'] = ipprofile
1977 update(scenario_net
['ip_profile'],ipprofile
)
1978 for interface
in net_instance_desc
.get('interfaces', () ):
1979 if 'ip_address' in interface
:
1980 for vnf
in scenarioDict
['vnfs']:
1981 if interface
['vnf'] == vnf
['name']:
1982 for vnf_interface
in vnf
['interfaces']:
1983 if interface
['vnf_interface'] == vnf_interface
['external_name']:
1984 vnf_interface
['ip_address']=interface
['ip_address']
1986 #logger.debug(">>>>>>>> Merged dictionary")
1987 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
1990 #1. Creating new nets (sce_nets) in the VIM"
1991 for sce_net
in scenarioDict
['nets']:
1992 sce_net
["vim_id_sites"]={}
1993 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
1994 net_name
= descriptor_net
.get("vim-network-name")
1995 auxNetDict
['scenario'][sce_net
['uuid']] = {}
1997 sites
= descriptor_net
.get("sites", [ {} ])
1999 if site
.get("datacenter"):
2000 vim
= myvims
[ site
["datacenter"] ]
2001 datacenter_id
= site
["datacenter"]
2003 vim
= myvims
[ default_datacenter_id
]
2004 datacenter_id
= default_datacenter_id
2005 net_type
= sce_net
['type']
2006 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
2007 if sce_net
["external"]:
2009 net_name
= sce_net
["name"]
2010 if "netmap-use" in site
or "netmap-create" in site
:
2011 create_network
= False
2012 lookfor_network
= False
2013 if "netmap-use" in site
:
2014 lookfor_network
= True
2015 if utils
.check_valid_uuid(site
["netmap-use"]):
2016 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2017 lookfor_filter
["id"] = site
["netmap-use"]
2019 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2020 lookfor_filter
["name"] = site
["netmap-use"]
2021 if "netmap-create" in site
:
2022 create_network
= True
2023 net_vim_name
= net_name
2024 if site
["netmap-create"]:
2025 net_vim_name
= site
["netmap-create"]
2027 elif sce_net
['vim_id'] != None:
2028 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
2029 create_network
= False
2030 lookfor_network
= True
2031 lookfor_filter
["id"] = sce_net
['vim_id']
2032 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
2033 #look for network at datacenter and return error
2035 #There is not a netmap, look at datacenter for a net with this name and create if not found
2036 create_network
= True
2037 lookfor_network
= True
2038 lookfor_filter
["name"] = sce_net
["name"]
2039 net_vim_name
= sce_net
["name"]
2040 filter_text
= "scenario name '%s'" % sce_net
["name"]
2043 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
2044 net_name
= net_name
[:255] #limit length
2045 net_vim_name
= net_name
2046 create_network
= True
2047 lookfor_network
= False
2050 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
2051 if len(vim_nets
) > 1:
2052 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2053 elif len(vim_nets
) == 0:
2054 if not create_network
:
2055 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2057 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
2058 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
2059 create_network
= False
2061 #if network is not external
2062 network_id
= vim
.new_network(net_vim_name
, net_type
, sce_net
.get('ip_profile',None))
2063 sce_net
["vim_id_sites"][datacenter_id
] = network_id
2064 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = network_id
2065 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':network_id
})
2066 sce_net
["created"] = True
2068 #2. Creating new nets (vnf internal nets) in the VIM"
2069 #For each vnf net, we create it and we add it to instanceNetlist.
2070 for sce_vnf
in scenarioDict
['vnfs']:
2071 for net
in sce_vnf
['nets']:
2072 if sce_vnf
.get("datacenter"):
2073 vim
= myvims
[ sce_vnf
["datacenter"] ]
2074 datacenter_id
= sce_vnf
["datacenter"]
2076 vim
= myvims
[ default_datacenter_id
]
2077 datacenter_id
= default_datacenter_id
2078 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
2079 net_name
= descriptor_net
.get("name")
2081 net_name
= "%s.%s" %(instance_name
, net
["name"])
2082 net_name
= net_name
[:255] #limit length
2083 net_type
= net
['type']
2084 network_id
= vim
.new_network(net_name
, net_type
, net
.get('ip_profile',None))
2085 net
['vim_id'] = network_id
2086 if sce_vnf
['uuid'] not in auxNetDict
:
2087 auxNetDict
[sce_vnf
['uuid']] = {}
2088 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2089 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2090 net
["created"] = True
2093 #print "auxNetDict:"
2094 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2096 #3. Creating new vm instances in the VIM
2097 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2098 for sce_vnf
in scenarioDict
['vnfs']:
2099 if sce_vnf
.get("datacenter"):
2100 vim
= myvims
[ sce_vnf
["datacenter"] ]
2101 datacenter_id
= sce_vnf
["datacenter"]
2103 vim
= myvims
[ default_datacenter_id
]
2104 datacenter_id
= default_datacenter_id
2105 sce_vnf
["datacenter_id"] = datacenter_id
2107 for vm
in sce_vnf
['vms']:
2110 myVMDict
['name'] = "{}.{}.{}".format(instance_name
,sce_vnf
['name'],chr(96+i
))
2111 myVMDict
['description'] = myVMDict
['name'][0:99]
2113 # myVMDict['start'] = "no"
2114 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2115 #create image at vim in case it not exist
2116 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2117 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2118 vm
['vim_image_id'] = image_id
2120 #create flavor at vim in case it not exist
2121 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2122 if flavor_dict
['extended']!=None:
2123 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2124 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
2129 #Obtain information for additional disks
2130 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
2131 if not extended_flavor_dict
:
2132 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
2135 #extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
2136 myVMDict
['disks'] = None
2137 extended_info
= extended_flavor_dict
[0]['extended']
2138 if extended_info
!= None:
2139 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
2140 if 'disks' in extended_flavor_dict_yaml
:
2141 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
2146 vm
['vim_flavor_id'] = flavor_id
2148 myVMDict
['imageRef'] = vm
['vim_image_id']
2149 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2150 myVMDict
['networks'] = []
2151 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
2152 for iface
in vm
['interfaces']:
2154 if iface
['type']=="data":
2155 netDict
['type'] = iface
['model']
2156 elif "model" in iface
and iface
["model"]!=None:
2157 netDict
['model']=iface
['model']
2158 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2159 #discover type of interface looking at flavor
2160 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2161 for flavor_iface
in numa
.get('interfaces',[]):
2162 if flavor_iface
.get('name') == iface
['internal_name']:
2163 if flavor_iface
['dedicated'] == 'yes':
2164 netDict
['type']="PF" #passthrough
2165 elif flavor_iface
['dedicated'] == 'no':
2166 netDict
['type']="VF" #siov
2167 elif flavor_iface
['dedicated'] == 'yes:sriov':
2168 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2169 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2171 netDict
["use"]=iface
['type']
2172 if netDict
["use"]=="data" and not netDict
.get("type"):
2173 #print "netDict", netDict
2174 #print "iface", iface
2175 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'])
2176 if flavor_dict
.get('extended')==None:
2177 raise NfvoException(e_text
+ "After database migration some information is not available. \
2178 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2180 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2181 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2182 netDict
["type"]="virtual"
2183 if "vpci" in iface
and iface
["vpci"] is not None:
2184 netDict
['vpci'] = iface
['vpci']
2185 if "mac" in iface
and iface
["mac"] is not None:
2186 netDict
['mac_address'] = iface
['mac']
2187 if "port-security" in iface
and iface
["port-security"] is not None:
2188 netDict
['port_security'] = iface
['port-security']
2189 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2190 netDict
['floating_ip'] = iface
['floating-ip']
2191 netDict
['name'] = iface
['internal_name']
2192 if iface
['net_id'] is None:
2193 for vnf_iface
in sce_vnf
["interfaces"]:
2196 if vnf_iface
['interface_id']==iface
['uuid']:
2197 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
2200 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2201 #skip bridge ifaces not connected to any net
2202 #if 'net_id' not in netDict or netDict['net_id']==None:
2204 myVMDict
['networks'].append(netDict
)
2205 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2206 #print myVMDict['name']
2207 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2208 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2209 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2210 if vm
.get("boot_data"):
2211 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
2213 cloud_config_vm
= cloud_config
2214 vm_id
= vim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
2215 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'], cloud_config
= cloud_config_vm
,
2216 disk_list
= myVMDict
['disks'])
2218 vm
['vim_id'] = vm_id
2219 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2220 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2221 for net
in myVMDict
['networks']:
2223 for iface
in vm
['interfaces']:
2224 if net
["name"]==iface
["internal_name"]:
2225 iface
["vim_id"]=net
["vim_id"]
2227 scenarioDict
["datacenter2tenant"] = datacenter2tenant
2228 logger
.debug("create_instance Deployment done scenarioDict: %s",
2229 yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False) )
2230 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
2231 return mydb
.get_instance_scenario(instance_id
)
2232 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2233 message
= rollback(mydb
, myvims
, rollbackList
)
2234 if isinstance(e
, db_base_Exception
):
2235 error_text
= "database Exception"
2236 elif isinstance(e
, vimconn
.vimconnException
):
2237 error_text
= "VIM Exception"
2239 error_text
= "Exception"
2240 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2241 #logger.error("create_instance: %s", error_text)
2242 raise NfvoException(error_text
, e
.http_code
)
2244 def delete_instance(mydb
, tenant_id
, instance_id
):
2245 #print "Checking that the instance_id exists and getting the instance dictionary"
2246 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2247 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2248 tenant_id
= instanceDict
["tenant_id"]
2249 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2251 #1. Delete from Database
2252 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2260 for sce_vnf
in instanceDict
['vnfs']:
2261 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2262 if datacenter_key
not in myvims
:
2263 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2264 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2266 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2267 sce_vnf
["datacenter_tenant_id"]))
2268 myvims
[datacenter_key
] = None
2270 myvims
[datacenter_key
] = vims
.values()[0]
2271 myvim
= myvims
[datacenter_key
]
2272 for vm
in sce_vnf
['vms']:
2274 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2277 myvim
.delete_vminstance(vm
['vim_vm_id'])
2278 except vimconn
.vimconnNotFoundException
as e
:
2279 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2280 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2281 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2282 except vimconn
.vimconnException
as e
:
2283 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2284 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2285 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2289 for net
in instanceDict
['nets']:
2290 if not net
['created']:
2291 continue #skip not created nets
2292 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2293 if datacenter_key
not in myvims
:
2294 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2295 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2297 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2298 myvims
[datacenter_key
] = None
2300 myvims
[datacenter_key
] = vims
.values()[0]
2301 myvim
= myvims
[datacenter_key
]
2304 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2307 myvim
.delete_network(net
['vim_net_id'])
2308 except vimconn
.vimconnNotFoundException
as e
:
2309 error_msg
+="\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2310 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2311 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2312 except vimconn
.vimconnException
as e
:
2313 error_msg
+="\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'], net
["datacenter_id"], e
.http_code
, str(e
))
2314 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2315 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2316 if len(error_msg
)>0:
2317 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2319 return 'instance ' + message
+ ' deleted'
2321 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2322 '''Refreshes a scenario instance. It modifies instanceDict'''
2324 - 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
2327 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2328 #print "nfvo.refresh_instance begins"
2329 #print json.dumps(instanceDict, indent=4)
2331 #print "Getting the VIM URL and the VIM tenant_id"
2334 # 1. Getting VIM vm and net list
2335 vms_updated
= [] #List of VM instance uuids in openmano that were updated
2338 for sce_vnf
in instanceDict
['vnfs']:
2339 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2340 if datacenter_key
not in vm_list
:
2341 vm_list
[datacenter_key
] = []
2342 if datacenter_key
not in myvims
:
2343 vims
= get_vim(mydb
, nfvo_tenant
, datacenter_id
=sce_vnf
["datacenter_id"],
2344 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2346 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"]))
2347 myvims
[datacenter_key
] = None
2349 myvims
[datacenter_key
] = vims
.values()[0]
2350 for vm
in sce_vnf
['vms']:
2351 vm_list
[datacenter_key
].append(vm
['vim_vm_id'])
2352 vms_notupdated
.append(vm
["uuid"])
2354 nets_updated
= [] #List of VM instance uuids in openmano that were updated
2357 for net
in instanceDict
['nets']:
2358 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2359 if datacenter_key
not in net_list
:
2360 net_list
[datacenter_key
] = []
2361 if datacenter_key
not in myvims
:
2362 vims
= get_vim(mydb
, nfvo_tenant
, datacenter_id
=net
["datacenter_id"],
2363 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2365 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2366 myvims
[datacenter_key
] = None
2368 myvims
[datacenter_key
] = vims
.values()[0]
2370 net_list
[datacenter_key
].append(net
['vim_net_id'])
2371 nets_notupdated
.append(net
["uuid"])
2373 # 1. Getting the status of all VMs
2375 for datacenter_key
in myvims
:
2376 if not vm_list
.get(datacenter_key
):
2380 if not myvims
[datacenter_key
]:
2381 failed_message
= "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"])
2384 vm_dict
.update(myvims
[datacenter_key
].refresh_vms_status(vm_list
[datacenter_key
]) )
2386 except vimconn
.vimconnException
as e
:
2387 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
2388 failed_message
= str(e
)
2390 for vm
in vm_list
[datacenter_key
]:
2391 vm_dict
[vm
] = {'status': "VIM_ERROR", 'error_msg': failed_message
}
2393 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2394 for sce_vnf
in instanceDict
['vnfs']:
2395 for vm
in sce_vnf
['vms']:
2396 vm_id
= vm
['vim_vm_id']
2397 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
2398 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2399 has_mgmt_iface
= False
2400 for iface
in vm
["interfaces"]:
2401 if iface
["type"]=="mgmt":
2402 has_mgmt_iface
= True
2403 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
2404 vm_dict
[vm_id
]['status'] = "ACTIVE"
2405 if vm_dict
[vm_id
].get('error_msg') and len(vm_dict
[vm_id
]['error_msg']) >= 1024:
2406 vm_dict
[vm_id
]['error_msg'] = vm_dict
[vm_id
]['error_msg'][:516] + " ... " + vm_dict
[vm_id
]['error_msg'][-500:]
2407 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'):
2408 vm
['status'] = vm_dict
[vm_id
]['status']
2409 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
2410 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
2411 # 2.1. Update in openmano DB the VMs whose status changed
2413 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
2414 vms_notupdated
.remove(vm
["uuid"])
2416 vms_updated
.append(vm
["uuid"])
2417 except db_base_Exception
as e
:
2418 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2419 # 2.2. Update in openmano DB the interface VMs
2420 for interface
in interfaces
:
2421 #translate from vim_net_id to instance_net_id
2423 for net
in instanceDict
['nets']:
2424 if net
["vim_net_id"] == interface
["vim_net_id"]:
2425 network_id_list
.append(net
["uuid"])
2426 if not network_id_list
:
2428 del interface
["vim_net_id"]
2430 for network_id
in network_id_list
:
2431 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
2432 except db_base_Exception
as e
:
2433 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
2435 # 3. Getting the status of all nets
2437 for datacenter_key
in myvims
:
2438 if not net_list
.get(datacenter_key
):
2442 if not myvims
[datacenter_key
]:
2443 failed_message
= "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"])
2446 net_dict
.update(myvims
[datacenter_key
].refresh_nets_status(net_list
[datacenter_key
]) )
2448 except vimconn
.vimconnException
as e
:
2449 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
2450 failed_message
= str(e
)
2452 for net
in net_list
[datacenter_key
]:
2453 net_dict
[net
] = {'status': "VIM_ERROR", 'error_msg': failed_message
}
2455 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2456 # TODO: update nets inside a vnf
2457 for net
in instanceDict
['nets']:
2458 net_id
= net
['vim_net_id']
2459 if net_dict
[net_id
].get('error_msg') and len(net_dict
[net_id
]['error_msg']) >= 1024:
2460 net_dict
[net_id
]['error_msg'] = net_dict
[net_id
]['error_msg'][:516] + " ... " + net_dict
[vm_id
]['error_msg'][-500:]
2461 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'):
2462 net
['status'] = net_dict
[net_id
]['status']
2463 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
2464 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
2465 # 5.1. Update in openmano DB the nets whose status changed
2467 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
2468 nets_notupdated
.remove(net
["uuid"])
2470 nets_updated
.append(net
["uuid"])
2471 except db_base_Exception
as e
:
2472 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2474 # Returns appropriate output
2475 #print "nfvo.refresh_instance finishes"
2476 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2477 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
2478 instance_id
= instanceDict
['uuid']
2479 if len(vms_notupdated
)+len(nets_notupdated
)>0:
2480 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
2481 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
2483 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2485 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2486 #print "Checking that the instance_id exists and getting the instance dictionary"
2487 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2488 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2490 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2491 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2493 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2494 myvim
= vims
.values()[0]
2497 input_vnfs
= action_dict
.pop("vnfs", [])
2498 input_vms
= action_dict
.pop("vms", [])
2499 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2503 for sce_vnf
in instanceDict
['vnfs']:
2504 for vm
in sce_vnf
['vms']:
2505 if not action_over_all
:
2506 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2507 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2510 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2511 if "console" in action_dict
:
2512 if not global_config
["http_console_proxy"]:
2513 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2514 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2515 protocol
=data
["protocol"],
2516 ip
= data
["server"],
2517 port
= data
["port"],
2518 suffix
= data
["suffix"]),
2522 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2523 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2524 "description": "this console is only reachable by local interface",
2529 #print "console data", data
2531 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2532 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2533 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2534 protocol
=data
["protocol"],
2535 ip
= global_config
["http_console_host"],
2536 port
= console_thread
.port
,
2537 suffix
= data
["suffix"]),
2541 except NfvoException
as e
:
2542 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2546 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2548 except vimconn
.vimconnException
as e
:
2549 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2552 if vm_ok
==0: #all goes wrong
2557 def create_or_use_console_proxy_thread(console_server
, console_port
):
2558 #look for a non-used port
2559 console_thread_key
= console_server
+ ":" + str(console_port
)
2560 if console_thread_key
in global_config
["console_thread"]:
2561 #global_config["console_thread"][console_thread_key].start_timeout()
2562 return global_config
["console_thread"][console_thread_key
]
2564 for port
in global_config
["console_port_iterator"]():
2565 #print "create_or_use_console_proxy_thread() port:", port
2566 if port
in global_config
["console_ports"]:
2569 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2571 global_config
["console_thread"][console_thread_key
] = clithread
2572 global_config
["console_ports"][port
] = console_thread_key
2574 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2575 #port used, try with onoher
2577 except cli
.ConsoleProxyException
as e
:
2578 raise NfvoException(str(e
), HTTP_Bad_Request
)
2579 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2581 def check_tenant(mydb
, tenant_id
):
2582 '''check that tenant exists at database'''
2583 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2585 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2588 def new_tenant(mydb
, tenant_dict
):
2589 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2592 def delete_tenant(mydb
, tenant
):
2593 #get nfvo_tenant info
2595 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2596 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2597 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2599 def new_datacenter(mydb
, datacenter_descriptor
):
2600 if "config" in datacenter_descriptor
:
2601 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2602 #Check that datacenter-type is correct
2603 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2606 module
= "vimconn_" + datacenter_type
2607 module_info
= imp
.find_module(module
)
2608 except (IOError, ImportError):
2609 if module_info
and module_info
[0]:
2610 file.close(module_info
[0])
2611 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2613 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2614 return datacenter_id
2616 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2617 #obtain data, check that only one exist
2618 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2620 datacenter_id
= datacenter
['uuid']
2621 where
={'uuid': datacenter
['uuid']}
2622 if "config" in datacenter_descriptor
:
2623 if datacenter_descriptor
['config']!=None:
2625 new_config_dict
= datacenter_descriptor
["config"]
2628 for k
in new_config_dict
:
2629 if new_config_dict
[k
]==None:
2632 config_dict
= yaml
.load(datacenter
["config"])
2633 config_dict
.update(new_config_dict
)
2637 except Exception as e
:
2638 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2639 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2640 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2641 return datacenter_id
2643 def delete_datacenter(mydb
, datacenter
):
2644 #get nfvo_tenant info
2645 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2646 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2647 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2649 def associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
2650 #get datacenter info
2651 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2652 datacenter_name
= myvim
["name"]
2654 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
2656 # get nfvo_tenant info
2657 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2658 if vim_tenant_name
==None:
2659 vim_tenant_name
=tenant_dict
['name']
2661 #check that this association does not exist before
2662 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2663 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2664 if len(tenants_datacenters
)>0:
2665 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2667 vim_tenant_id_exist_atdb
=False
2668 if not create_vim_tenant
:
2669 where_
={"datacenter_id": datacenter_id
}
2670 if vim_tenant_id
!=None:
2671 where_
["vim_tenant_id"] = vim_tenant_id
2672 if vim_tenant_name
!=None:
2673 where_
["vim_tenant_name"] = vim_tenant_name
2674 #check if vim_tenant_id is already at database
2675 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2676 if len(datacenter_tenants_dict
)>=1:
2677 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2678 vim_tenant_id_exist_atdb
=True
2679 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2681 datacenter_tenants_dict
= {}
2682 #insert at table datacenter_tenants
2683 else: #if vim_tenant_id==None:
2684 #create tenant at VIM if not provided
2686 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2687 except vimconn
.vimconnException
as e
:
2688 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2689 datacenter_tenants_dict
= {}
2690 datacenter_tenants_dict
["created"]="true"
2692 #fill datacenter_tenants table
2693 if not vim_tenant_id_exist_atdb
:
2694 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2695 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2696 datacenter_tenants_dict
["user"] = vim_username
2697 datacenter_tenants_dict
["passwd"] = vim_password
2698 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2700 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
2701 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2702 datacenter_tenants_dict
["uuid"] = id_
2704 #fill tenants_datacenters table
2705 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2706 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2708 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
2709 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
2710 new_thread
= vim_thread
.vim_thread(myvim
, thread_name
)
2712 vim_threads
["running"][datacenter_id
+ "-" + tenant_dict
['uuid']] = new_thread
2714 return datacenter_id
2716 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2717 #get datacenter info
2718 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2720 #get nfvo_tenant info
2721 if not tenant_id
or tenant_id
=="any":
2724 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2725 tenant_uuid
= tenant_dict
['uuid']
2727 #check that this association exist before
2728 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2730 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2731 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2732 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2733 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2735 #delete this association
2736 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2738 #get vim_tenant info and deletes
2740 for tenant_datacenter_item
in tenant_datacenter_list
:
2741 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2742 #try to delete vim:tenant
2744 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2745 if vim_tenant_dict
['created']=='true':
2746 #delete tenant at VIM if created by NFVO
2748 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2749 except vimconn
.vimconnException
as e
:
2750 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2751 logger
.warn(warning
)
2752 except db_base_Exception
as e
:
2753 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2754 pass # the error will be caused because dependencies, vim_tenant can not be deleted
2755 thread_id
= datacenter_id
+ "-" + tenant_datacenter_item
["nfvo_tenant_id"]
2756 thread
= vim_threads
["running"][thread_id
]
2757 thread
.insert_task("exit")
2758 vim_threads
["deleting"][thread_id
] = thread
2759 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2761 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2763 #get datacenter info
2764 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2766 if 'net-update' in action_dict
:
2768 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2770 except vimconn
.vimconnException
as e
:
2771 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2772 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2773 #update nets Change from VIM format to NFVO format
2776 net_nfvo
={'datacenter_id': datacenter_id
}
2777 net_nfvo
['name'] = net
['name']
2778 #net_nfvo['description']= net['name']
2779 net_nfvo
['vim_net_id'] = net
['id']
2780 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2781 net_nfvo
['shared'] = net
['shared']
2782 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2783 net_list
.append(net_nfvo
)
2784 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2785 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2787 elif 'net-edit' in action_dict
:
2788 net
= action_dict
['net-edit'].pop('net')
2789 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2790 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2791 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2793 elif 'net-delete' in action_dict
:
2794 net
= action_dict
['net-deelte'].get('net')
2795 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2796 result
= mydb
.delete_row(FROM
='datacenter_nets',
2797 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2801 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2803 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2804 #get datacenter info
2805 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2807 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2808 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2809 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2812 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2813 #get datacenter info
2814 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2817 action_dict
= action_dict
["netmap"]
2818 if 'vim_id' in action_dict
:
2819 filter_dict
["id"] = action_dict
['vim_id']
2820 if 'vim_name' in action_dict
:
2821 filter_dict
["name"] = action_dict
['vim_name']
2823 filter_dict
["shared"] = True
2826 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
2827 except vimconn
.vimconnException
as e
:
2828 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
2829 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2830 if len(vim_nets
)>1 and action_dict
:
2831 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
2832 elif len(vim_nets
)==0: # and action_dict:
2833 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
2835 for net
in vim_nets
:
2836 net_nfvo
={'datacenter_id': datacenter_id
}
2837 if action_dict
and "name" in action_dict
:
2838 net_nfvo
['name'] = action_dict
['name']
2840 net_nfvo
['name'] = net
['name']
2841 #net_nfvo['description']= net['name']
2842 net_nfvo
['vim_net_id'] = net
['id']
2843 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2844 net_nfvo
['shared'] = net
['shared']
2845 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2847 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
2848 net_nfvo
["status"] = "OK"
2849 net_nfvo
["uuid"] = net_id
2850 except db_base_Exception
as e
:
2854 net_nfvo
["status"] = "FAIL: " + str(e
)
2855 net_list
.append(net_nfvo
)
2858 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
2859 #get datacenter info
2860 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2863 if utils
.check_valid_uuid(name
):
2864 filter_dict
["id"] = name
2866 filter_dict
["name"] = name
2868 if item
=="networks":
2869 #filter_dict['tenant_id'] = myvim['tenant_id']
2870 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
2871 elif item
=="tenants":
2872 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
2873 elif item
== "images":
2874 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
2876 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2877 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
2878 if name
and len(content
)==1:
2879 return {item
[:-1]: content
[0]}
2880 elif name
and len(content
)==0:
2881 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
2884 return {item
: content
}
2885 except vimconn
.vimconnException
as e
:
2886 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
2887 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
2889 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
2890 #get datacenter info
2891 if tenant_id
== "any":
2894 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2896 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
2897 logger
.debug("vim_action_delete vim response: " + str(content
))
2898 items
= content
.values()[0]
2899 if type(items
)==list and len(items
)==0:
2900 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
2901 elif type(items
)==list and len(items
)>1:
2902 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
2903 else: # it is a dict
2904 item_id
= items
["id"]
2905 item_name
= str(items
.get("name"))
2908 if item
=="networks":
2909 content
= myvim
.delete_network(item_id
)
2910 elif item
=="tenants":
2911 content
= myvim
.delete_tenant(item_id
)
2912 elif item
== "images":
2913 content
= myvim
.delete_image(item_id
)
2915 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2916 except vimconn
.vimconnException
as e
:
2917 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
2918 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
2920 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
2922 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
2923 #get datacenter info
2924 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
2925 if tenant_id
== "any":
2927 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2929 if item
=="networks":
2930 net
= descriptor
["network"]
2931 net_name
= net
.pop("name")
2932 net_type
= net
.pop("type", "bridge")
2933 net_public
= net
.pop("shared", False)
2934 net_ipprofile
= net
.pop("ip_profile", None)
2935 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, **net
)
2936 elif item
=="tenants":
2937 tenant
= descriptor
["tenant"]
2938 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
2940 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
2941 except vimconn
.vimconnException
as e
:
2942 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
2944 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)