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 from threading
import Lock
46 #import openvim.ovim as Ovim
49 global vimconn_imported
51 global default_volume_size
52 default_volume_size
= '5' #size in GB
57 vimconn_imported
= {} # dictionary with VIM type as key, loaded module as value
58 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
59 vim_persistent_info
= {}
60 logger
= logging
.getLogger('openmano.nfvo')
67 class NfvoException(Exception):
68 def __init__(self
, message
, http_code
):
69 self
.http_code
= http_code
70 Exception.__init
__(self
, message
)
76 if task_id
<= last_task_id
:
77 task_id
= last_task_id
+ 0.000001
78 last_task_id
= task_id
79 return "TASK.{:.6f}".format(task_id
)
82 def new_task(name
, params
, store
=True, depends
=None):
83 task_id
= get_task_id()
84 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
86 task
["depends"] = depends
88 task_dict
[task_id
] = task
93 return True if id[:5] == "TASK." else False
96 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
97 name
= datacenter_name
[:16]
98 if name
not in vim_threads
["names"]:
99 vim_threads
["names"].append(name
)
101 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
102 if name
not in vim_threads
["names"]:
103 vim_threads
["names"].append(name
)
105 name
= datacenter_id
+ "-" + tenant_id
106 vim_threads
["names"].append(name
)
110 def start_service(mydb
):
111 global db
, global_config
112 db
= nfvo_db
.nfvo_db()
113 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
116 # Initialize openvim for SDN control
117 # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
118 # TODO: review ovim.py to delete not needed configuration
119 ovim_configuration
= {
120 'logger_name': 'openvim',
121 'network_vlan_range_start': 1000,
122 'network_vlan_range_end': 4096,
123 'log_level_db': 'DEBUG',
124 'db_name': 'mano_vim_db',
125 'db_host': 'localhost',
127 'db_passwd': 'vimpw',
128 'database_version': '0.15',
131 'of_controller_nets_with_same_vlan': True,
132 'network_type': 'bridge',
133 #TODO: log_level_of should not be needed. To be modified in ovim
134 'log_level_of': 'DEBUG'
136 #ovim = Ovim.ovim(ovim_configuration)
137 #ovim.start_service()
139 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'
140 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
141 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
142 'user','passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
144 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
146 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
148 extra
.update(yaml
.load(vim
["config"]))
149 if vim
.get('dt_config'):
150 extra
.update(yaml
.load(vim
["dt_config"]))
151 if vim
["type"] not in vimconn_imported
:
154 module
= "vimconn_" + vim
["type"]
155 module_info
= imp
.find_module(module
)
156 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
157 vimconn_imported
[vim
["type"]] = vim_conn
158 except (IOError, ImportError) as e
:
159 if module_info
and module_info
[0]:
160 file.close(module_info
[0])
161 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
162 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
164 thread_id
= vim
["datacenter_id"] + "." + vim
['nfvo_tenant_id']
165 vim_persistent_info
[thread_id
] = {}
168 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
169 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
170 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
171 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
172 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
173 user
=vim
['user'], passwd
=vim
['passwd'],
174 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
176 except Exception as e
:
177 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
178 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['vim_tenant_id'], vim
['vim_tenant_name'], vim
['vim_tenant_id'])
179 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, vim
['datacenter_name'],
180 vim
.get('datacenter_tenant_id'), db
=db
, db_lock
=db_lock
, ovim
=ovim
)
182 vim_threads
["running"][thread_id
] = new_thread
183 except db_base_Exception
as e
:
184 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
189 for thread_id
,thread
in vim_threads
["running"].items():
190 thread
.insert_task(new_task("exit", None, store
=False))
191 vim_threads
["deleting"][thread_id
] = thread
192 vim_threads
["running"] = {}
195 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
197 return result, content:
198 <0, error_text upon error
199 nb_records, flavor_list on success
202 WHERE_dict
['vnf_id'] = vnf_id
203 if nfvo_tenant
is not None:
204 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
206 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
207 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
208 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
209 #print "get_flavor_list result:", result
210 #print "get_flavor_list content:", content
212 for flavor
in flavors
:
213 flavorList
.append(flavor
['flavor_id'])
217 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
219 return result, content:
220 <0, error_text upon error
221 nb_records, flavor_list on success
224 WHERE_dict
['vnf_id'] = vnf_id
225 if nfvo_tenant
is not None:
226 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
228 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
229 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
232 imageList
.append(image
['image_id'])
236 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
237 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
238 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
239 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
240 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
241 raise exception upon error
244 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
245 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
246 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
247 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
248 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
249 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
250 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
251 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'
252 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
253 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
254 'user','passwd', 'dt.config as dt_config')
256 from_
= 'datacenters as d'
257 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
259 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
262 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
264 extra
.update(yaml
.load(vim
["config"]))
265 if vim
.get('dt_config'):
266 extra
.update(yaml
.load(vim
["dt_config"]))
267 if vim
["type"] not in vimconn_imported
:
270 module
= "vimconn_" + vim
["type"]
271 module_info
= imp
.find_module(module
)
272 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
273 vimconn_imported
[vim
["type"]] = vim_conn
274 except (IOError, ImportError) as e
:
275 if module_info
and module_info
[0]:
276 file.close(module_info
[0])
277 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
278 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
281 if 'nfvo_tenant_id' in vim
:
282 thread_id
= vim
["datacenter_id"] + "." + vim
['nfvo_tenant_id']
283 if thread_id
not in vim_persistent_info
:
284 vim_persistent_info
[thread_id
] = {}
285 persistent_info
= vim_persistent_info
[thread_id
]
289 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
290 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
291 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
292 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
293 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
294 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
295 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
296 config
=extra
, persistent_info
=persistent_info
298 except Exception as e
:
299 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
301 except db_base_Exception
as e
:
302 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
305 def rollback(mydb
, vims
, rollback_list
):
307 #delete things by reverse order
308 for i
in range(len(rollback_list
)-1, -1, -1):
309 item
= rollback_list
[i
]
310 if item
["where"]=="vim":
311 if item
["vim_id"] not in vims
:
313 vim
=vims
[ item
["vim_id"] ]
315 if item
["what"]=="image":
316 vim
.delete_image(item
["uuid"])
317 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
318 elif item
["what"]=="flavor":
319 vim
.delete_flavor(item
["uuid"])
320 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
321 elif item
["what"]=="network":
322 vim
.delete_network(item
["uuid"])
323 elif item
["what"]=="vm":
324 vim
.delete_vminstance(item
["uuid"])
325 except vimconn
.vimconnException
as e
:
326 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
327 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
328 except db_base_Exception
as e
:
329 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
333 if item
["what"]=="image":
334 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
335 elif item
["what"]=="flavor":
336 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
337 except db_base_Exception
as e
:
338 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
339 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
340 if len(undeleted_items
)==0:
341 return True," Rollback successful."
343 return False," Rollback fails to delete: " + str(undeleted_items
)
346 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
348 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
350 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
352 #dataplane interfaces
353 for numa
in vnfc
.get("numas",() ):
354 for interface
in numa
.get("interfaces",()):
355 if interface
["name"] in name_dict
:
357 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
358 vnfc
["name"], interface
["name"]),
360 name_dict
[ interface
["name"] ] = "underlay"
362 for interface
in vnfc
.get("bridge-ifaces",() ):
363 if interface
["name"] in name_dict
:
365 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
366 vnfc
["name"], interface
["name"]),
368 name_dict
[ interface
["name"] ] = "overlay"
369 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
370 # check bood-data info
371 if "boot-data" in vnfc
:
372 # check that user-data is incompatible with users and config-files
373 if (vnfc
["boot-data"].get("users") or vnfc
["boot-data"].get("config-files")) and vnfc
["boot-data"].get("user-data"):
375 "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
378 #check if the info in external_connections matches with the one in the vnfcs
380 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
381 if external_connection
["name"] in name_list
:
383 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
384 external_connection
["name"]),
386 name_list
.append(external_connection
["name"])
387 if external_connection
["VNFC"] not in vnfc_interfaces
:
389 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
390 external_connection
["name"], external_connection
["VNFC"]),
393 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
395 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
396 external_connection
["name"],
397 external_connection
["local_iface_name"]),
400 #check if the info in internal_connections matches with the one in the vnfcs
402 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
403 if internal_connection
["name"] in name_list
:
405 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
406 internal_connection
["name"]),
408 name_list
.append(internal_connection
["name"])
409 #We should check that internal-connections of type "ptp" have only 2 elements
411 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
413 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
414 internal_connection
["name"],
415 'ptp' if vnf_descriptor_version
==1 else 'e-line',
416 'data' if vnf_descriptor_version
==1 else "e-lan"),
418 for port
in internal_connection
["elements"]:
420 iface
= port
["local_iface_name"]
421 if vnf
not in vnfc_interfaces
:
423 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
424 internal_connection
["name"], vnf
),
426 if iface
not in vnfc_interfaces
[ vnf
]:
428 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
429 internal_connection
["name"], iface
),
431 return -HTTP_Bad_Request
,
432 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
433 if vnfc_interfaces
[vnf
][iface
] == "overlay":
434 internal_connection
["type"] = "bridge"
436 internal_connection
["type"] = "data"
437 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
438 if vnfc_interfaces
[vnf
][iface
] == "overlay":
439 internal_connection
["implementation"] = "overlay"
441 internal_connection
["implementation"] = "underlay"
442 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
443 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
445 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
446 internal_connection
["name"],
447 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
448 'data' if vnf_descriptor_version
==1 else 'underlay'),
450 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
451 vnfc_interfaces
[vnf
][iface
] == "underlay":
453 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
454 internal_connection
["name"], iface
,
455 'data' if vnf_descriptor_version
==1 else 'underlay',
456 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
460 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
462 if only_create_at_vim
:
463 image_mano_id
= image_dict
['uuid']
464 if return_on_error
== None:
465 return_on_error
= True
467 if image_dict
['location']:
468 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
470 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
472 image_mano_id
= images
[0]['uuid']
474 #create image in MANO DB
475 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
476 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
477 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
479 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
480 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
481 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
482 #create image at every vim
483 for vim_id
,vim
in vims
.iteritems():
484 image_created
="false"
486 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
487 #look at VIM if this image exist
489 if image_dict
['location'] is not None:
490 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
493 filter_dict
['name'] = image_dict
['universal_name']
494 if image_dict
.get('checksum') != None:
495 filter_dict
['checksum'] = image_dict
['checksum']
496 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
497 vim_images
= vim
.get_image_list(filter_dict
)
498 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
499 if len(vim_images
) > 1:
500 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), HTTP_Conflict
)
501 elif len(vim_images
) == 0:
502 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
504 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
505 image_vim_id
= vim_images
[0]['id']
507 except vimconn
.vimconnNotFoundException
as e
:
508 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
510 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
511 if image_dict
['location']:
512 image_vim_id
= vim
.new_image(image_dict
)
513 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
516 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
517 raise vimconn
.vimconnException(str(e
))
518 except vimconn
.vimconnException
as e
:
520 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
523 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
525 except vimconn
.vimconnException
as e
:
527 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
529 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
532 #if we reach here, the image has been created or existed
534 #add new vim_id at datacenters_images
535 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
536 elif image_db
[0]["vim_id"]!=image_vim_id
:
537 #modify existing vim_id at datacenters_images
538 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
540 return image_vim_id
if only_create_at_vim
else image_mano_id
543 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
544 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
545 'ram':flavor_dict
.get('ram'),
546 'vcpus':flavor_dict
.get('vcpus'),
548 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
549 del flavor_dict
['extended']
550 if 'extended' in flavor_dict
:
551 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
553 #look if flavor exist
554 if only_create_at_vim
:
555 flavor_mano_id
= flavor_dict
['uuid']
556 if return_on_error
== None:
557 return_on_error
= True
559 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
561 flavor_mano_id
= flavors
[0]['uuid']
564 #create one by one the images of aditional disks
565 dev_image_list
=[] #list of images
566 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
568 for device
in flavor_dict
['extended'].get('devices',[]):
569 if "image" not in device
and "image name" not in device
:
572 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
573 image_dict
['universal_name']=device
.get('image name')
574 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
575 image_dict
['location']=device
.get('image')
576 #image_dict['new_location']=vnfc.get('image location')
577 image_dict
['checksum']=device
.get('image checksum')
578 image_metadata_dict
= device
.get('image metadata', None)
579 image_metadata_str
= None
580 if image_metadata_dict
!= None:
581 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
582 image_dict
['metadata']=image_metadata_str
583 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
584 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
585 dev_image_list
.append(image_id
)
587 temp_flavor_dict
['name'] = flavor_dict
['name']
588 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
589 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
590 flavor_mano_id
= content
591 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
592 #create flavor at every vim
593 if 'uuid' in flavor_dict
:
594 del flavor_dict
['uuid']
596 for vim_id
,vim
in vims
.items():
597 flavor_created
="false"
599 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
600 #look at VIM if this flavor exist SKIPPED
601 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
603 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
607 #Create the flavor in VIM
608 #Translate images at devices from MANO id to VIM id
610 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
611 #make a copy of original devices
614 for device
in flavor_dict
["extended"].get("devices",[]):
617 devices_original
.append(dev
)
618 if 'image' in device
:
620 if 'image metadata' in device
:
621 del device
['image metadata']
623 for index
in range(0,len(devices_original
)) :
624 device
=devices_original
[index
]
625 if "image" not in device
and "image name" not in device
:
627 disk_list
.append({'size': device
.get('size', default_volume_size
)})
630 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
631 image_dict
['universal_name']=device
.get('image name')
632 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
633 image_dict
['location']=device
.get('image')
634 #image_dict['new_location']=device.get('image location')
635 image_dict
['checksum']=device
.get('image checksum')
636 image_metadata_dict
= device
.get('image metadata', None)
637 image_metadata_str
= None
638 if image_metadata_dict
!= None:
639 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
640 image_dict
['metadata']=image_metadata_str
641 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
642 image_dict
["uuid"]=image_mano_id
643 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
645 #save disk information (image must be based on and size
646 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
648 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
651 #check that this vim_id exist in VIM, if not create
652 flavor_vim_id
=flavor_db
[0]["vim_id"]
654 vim
.get_flavor(flavor_vim_id
)
655 continue #flavor exist
656 except vimconn
.vimconnException
:
658 #create flavor at vim
659 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
662 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
663 flavor_create
="false"
664 except vimconn
.vimconnException
as e
:
667 if not flavor_vim_id
:
668 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
669 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
670 flavor_created
="true"
671 except vimconn
.vimconnException
as e
:
673 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
675 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
678 #if reach here the flavor has been create or exist
679 if len(flavor_db
)==0:
680 #add new vim_id at datacenters_flavors
681 extended_devices_yaml
= None
682 if len(disk_list
) > 0:
683 extended_devices
= dict()
684 extended_devices
['disks'] = disk_list
685 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
686 mydb
.new_row('datacenters_flavors',
687 {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
,
688 'created':flavor_created
,'extended': extended_devices_yaml
})
689 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
690 #modify existing vim_id at datacenters_flavors
691 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
693 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
696 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
699 # Step 1. Check the VNF descriptor
700 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
701 # Step 2. Check tenant exist
703 if tenant_id
!= "any":
704 check_tenant(mydb
, tenant_id
)
705 if "tenant_id" in vnf_descriptor
["vnf"]:
706 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
707 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
710 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
711 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
712 if global_config
["auto_push_VNF_to_VIMs"]:
713 vims
= get_vim(mydb
, tenant_id
)
715 # Step 4. Review the descriptor and add missing fields
716 #print vnf_descriptor
717 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
718 vnf_name
= vnf_descriptor
['vnf']['name']
719 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
720 if "physical" in vnf_descriptor
['vnf']:
721 del vnf_descriptor
['vnf']['physical']
722 #print vnf_descriptor
724 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
725 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
726 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
728 #For each VNFC, we add it to the VNFCDict and we create a flavor.
729 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
730 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
732 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
733 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
735 VNFCitem
["name"] = vnfc
['name']
736 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
738 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
741 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
742 myflavorDict
["description"] = VNFCitem
["description"]
743 myflavorDict
["ram"] = vnfc
.get("ram", 0)
744 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
745 myflavorDict
["disk"] = vnfc
.get("disk", 1)
746 myflavorDict
["extended"] = {}
748 devices
= vnfc
.get("devices")
750 myflavorDict
["extended"]["devices"] = devices
753 # 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
754 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
756 # Previous code has been commented
757 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
758 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
759 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
760 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
762 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
764 # print "Error creating flavor: unknown processor model. Rollback successful."
765 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
767 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
768 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
770 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
771 myflavorDict
['extended']['numas'] = vnfc
['numas']
775 # Step 6.2 New flavors are created in the VIM
776 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
778 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
779 VNFCitem
["flavor_id"] = flavor_id
780 VNFCDict
[vnfc
['name']] = VNFCitem
782 logger
.debug("Creating new images in the VIM for each VNFC")
783 # Step 6.3 New images are created in the VIM
784 #For each VNFC, we must create the appropriate image.
785 #This "for" loop might be integrated with the previous one
786 #In case this integration is made, the VNFCDict might become a VNFClist.
787 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
788 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
790 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
791 image_dict
['universal_name']=vnfc
.get('image name')
792 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
793 image_dict
['location']=vnfc
.get('VNFC image')
794 #image_dict['new_location']=vnfc.get('image location')
795 image_dict
['checksum']=vnfc
.get('image checksum')
796 image_metadata_dict
= vnfc
.get('image metadata', None)
797 image_metadata_str
= None
798 if image_metadata_dict
is not None:
799 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
800 image_dict
['metadata']=image_metadata_str
801 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
802 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
803 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
804 VNFCDict
[vnfc
['name']]["image_id"] = image_id
805 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
806 if vnfc
.get("boot-data"):
807 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
810 # Step 7. Storing the VNF descriptor in the repository
811 if "descriptor" not in vnf_descriptor
["vnf"]:
812 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
814 # Step 8. Adding the VNF to the NFVO DB
815 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
817 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
818 _
, message
= rollback(mydb
, vims
, rollback_list
)
819 if isinstance(e
, db_base_Exception
):
820 error_text
= "Exception at database"
821 elif isinstance(e
, KeyError):
822 error_text
= "KeyError exception "
823 e
.http_code
= HTTP_Internal_Server_Error
825 error_text
= "Exception at VIM"
826 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
827 #logger.error("start_scenario %s", error_text)
828 raise NfvoException(error_text
, e
.http_code
)
831 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
834 # Step 1. Check the VNF descriptor
835 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
836 # Step 2. Check tenant exist
838 if tenant_id
!= "any":
839 check_tenant(mydb
, tenant_id
)
840 if "tenant_id" in vnf_descriptor
["vnf"]:
841 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
842 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
845 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
846 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
847 if global_config
["auto_push_VNF_to_VIMs"]:
848 vims
= get_vim(mydb
, tenant_id
)
850 # Step 4. Review the descriptor and add missing fields
851 #print vnf_descriptor
852 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
853 vnf_name
= vnf_descriptor
['vnf']['name']
854 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
855 if "physical" in vnf_descriptor
['vnf']:
856 del vnf_descriptor
['vnf']['physical']
857 #print vnf_descriptor
859 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
860 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
861 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
863 #For each VNFC, we add it to the VNFCDict and we create a flavor.
864 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
865 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
867 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
868 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
870 VNFCitem
["name"] = vnfc
['name']
871 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
873 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
876 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
877 myflavorDict
["description"] = VNFCitem
["description"]
878 myflavorDict
["ram"] = vnfc
.get("ram", 0)
879 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
880 myflavorDict
["disk"] = vnfc
.get("disk", 1)
881 myflavorDict
["extended"] = {}
883 devices
= vnfc
.get("devices")
885 myflavorDict
["extended"]["devices"] = devices
888 # 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
889 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
891 # Previous code has been commented
892 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
893 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
894 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
895 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
897 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
899 # print "Error creating flavor: unknown processor model. Rollback successful."
900 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
902 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
903 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
905 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
906 myflavorDict
['extended']['numas'] = vnfc
['numas']
910 # Step 6.2 New flavors are created in the VIM
911 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
913 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
914 VNFCitem
["flavor_id"] = flavor_id
915 VNFCDict
[vnfc
['name']] = VNFCitem
917 logger
.debug("Creating new images in the VIM for each VNFC")
918 # Step 6.3 New images are created in the VIM
919 #For each VNFC, we must create the appropriate image.
920 #This "for" loop might be integrated with the previous one
921 #In case this integration is made, the VNFCDict might become a VNFClist.
922 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
923 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
925 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
926 image_dict
['universal_name']=vnfc
.get('image name')
927 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
928 image_dict
['location']=vnfc
.get('VNFC image')
929 #image_dict['new_location']=vnfc.get('image location')
930 image_dict
['checksum']=vnfc
.get('image checksum')
931 image_metadata_dict
= vnfc
.get('image metadata', None)
932 image_metadata_str
= None
933 if image_metadata_dict
is not None:
934 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
935 image_dict
['metadata']=image_metadata_str
936 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
937 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
938 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
939 VNFCDict
[vnfc
['name']]["image_id"] = image_id
940 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
941 if vnfc
.get("boot-data"):
942 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
944 # Step 7. Storing the VNF descriptor in the repository
945 if "descriptor" not in vnf_descriptor
["vnf"]:
946 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
948 # Step 8. Adding the VNF to the NFVO DB
949 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
951 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
952 _
, message
= rollback(mydb
, vims
, rollback_list
)
953 if isinstance(e
, db_base_Exception
):
954 error_text
= "Exception at database"
955 elif isinstance(e
, KeyError):
956 error_text
= "KeyError exception "
957 e
.http_code
= HTTP_Internal_Server_Error
959 error_text
= "Exception at VIM"
960 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
961 #logger.error("start_scenario %s", error_text)
962 raise NfvoException(error_text
, e
.http_code
)
965 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
966 #check valid tenant_id
967 check_tenant(mydb
, tenant_id
)
970 if tenant_id
!= "any":
971 where_or
["tenant_id"] = tenant_id
972 where_or
["public"] = True
973 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
976 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
977 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
978 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
979 data
={'vnf' : filtered_content
}
981 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
982 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description', 'boot_data'),
983 WHERE
={'vnfs.uuid': vnf_id
} )
985 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
986 # change boot_data into boot-data
988 if vm
.get("boot_data"):
989 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
992 data
['vnf']['VNFC'] = content
993 #TODO: GET all the information from a VNFC and include it in the output.
996 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
997 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
998 WHERE
={'vnfs.uuid': vnf_id
} )
999 data
['vnf']['nets'] = content
1001 #GET ip-profile for each net
1002 for net
in data
['vnf']['nets']:
1003 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1004 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1005 WHERE
={'net_id': net
["uuid"]} )
1006 if len(ipprofiles
)==1:
1007 net
["ip_profile"] = ipprofiles
[0]
1008 elif len(ipprofiles
)>1:
1009 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
1012 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1014 #GET External Interfaces
1015 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1016 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1017 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1018 WHERE
={'vnfs.uuid': vnf_id
},
1019 WHERE_NOT
={'interfaces.external_name': None} )
1021 data
['vnf']['external-connections'] = content
1026 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1027 # Check tenant exist
1028 if tenant_id
!= "any":
1029 check_tenant(mydb
, tenant_id
)
1030 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1031 vims
= get_vim(mydb
, tenant_id
)
1035 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1037 if tenant_id
!= "any":
1038 where_or
["tenant_id"] = tenant_id
1039 where_or
["public"] = True
1040 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1041 vnf_id
= vnf
["uuid"]
1043 # "Getting the list of flavors and tenants of the VNF"
1044 flavorList
= get_flavorlist(mydb
, vnf_id
)
1045 if len(flavorList
)==0:
1046 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1048 imageList
= get_imagelist(mydb
, vnf_id
)
1049 if len(imageList
)==0:
1050 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1052 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1054 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1057 for flavor
in flavorList
:
1058 #check if flavor is used by other vnf
1060 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1062 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1064 #flavor not used, must be deleted
1066 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
1067 for flavor_vim
in c
:
1068 if flavor_vim
["datacenter_id"] not in vims
:
1070 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
1072 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
1074 myvim
.delete_flavor(flavor_vim
["vim_id"])
1075 except vimconn
.vimconnNotFoundException
as e
:
1076 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
1077 except vimconn
.vimconnException
as e
:
1078 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1079 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1080 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
1081 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1082 mydb
.delete_row_by_id('flavors', flavor
)
1083 except db_base_Exception
as e
:
1084 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1085 undeletedItems
.append("flavor %s" % flavor
)
1088 for image
in imageList
:
1090 #check if image is used by other vnf
1091 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1093 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1095 #image not used, must be deleted
1097 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1099 if image_vim
["datacenter_id"] not in vims
:
1101 if image_vim
['created']=='false': #skip this image because not created by openmano
1103 myvim
=vims
[ image_vim
["datacenter_id"] ]
1105 myvim
.delete_image(image_vim
["vim_id"])
1106 except vimconn
.vimconnNotFoundException
as e
:
1107 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1108 except vimconn
.vimconnException
as e
:
1109 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1110 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1111 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1112 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1113 mydb
.delete_row_by_id('images', image
)
1114 except db_base_Exception
as e
:
1115 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1116 undeletedItems
.append("image %s" % image
)
1118 return vnf_id
+ " " + vnf
["name"]
1120 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1123 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1124 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1128 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1129 myvim
= vims
.values()[0]
1130 result
,servers
= myvim
.get_hosts_info()
1132 return result
, servers
1133 topology
= {'name':myvim
['name'] , 'servers': servers
}
1134 return result
, topology
1137 def get_hosts(mydb
, nfvo_tenant_id
):
1138 vims
= get_vim(mydb
, nfvo_tenant_id
)
1140 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1142 #print "nfvo.datacenter_action() error. Several datacenters found"
1143 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1144 myvim
= vims
.values()[0]
1146 hosts
= myvim
.get_hosts()
1147 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1149 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1151 server
={'name':host
['name'], 'vms':[]}
1152 for vm
in host
['instances']:
1153 #get internal name and model
1155 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1156 WHERE
={'vim_vm_id':vm
['id']} )
1158 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1160 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1162 except db_base_Exception
as e
:
1163 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1164 datacenter
['Datacenters'][0]['servers'].append(server
)
1165 #return -400, "en construccion"
1167 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1169 except vimconn
.vimconnException
as e
:
1170 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1173 def new_scenario(mydb
, tenant_id
, topo
):
1175 # result, vims = get_vim(mydb, tenant_id)
1177 # return result, vims
1179 if tenant_id
!= "any":
1180 check_tenant(mydb
, tenant_id
)
1181 if "tenant_id" in topo
:
1182 if topo
["tenant_id"] != tenant_id
:
1183 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1188 #1.1: get VNFs and external_networks (other_nets).
1190 other_nets
={} #external_networks, bridge_networks and data_networkds
1191 nodes
= topo
['topology']['nodes']
1192 for k
in nodes
.keys():
1193 if nodes
[k
]['type'] == 'VNF':
1195 vnfs
[k
]['ifaces'] = {}
1196 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1197 other_nets
[k
] = nodes
[k
]
1198 other_nets
[k
]['external']=True
1199 elif nodes
[k
]['type'] == 'network':
1200 other_nets
[k
] = nodes
[k
]
1201 other_nets
[k
]['external']=False
1204 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1205 for name
,vnf
in vnfs
.items():
1207 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1209 error_pos
= "'topology':'nodes':'" + name
+ "'"
1211 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1212 where
['uuid'] = vnf
['vnf_id']
1213 if 'VNF model' in vnf
:
1214 error_text
+= " 'VNF model' " + vnf
['VNF model']
1215 where
['name'] = vnf
['VNF model']
1217 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1219 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1225 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1227 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1228 vnf
['uuid']=vnf_db
[0]['uuid']
1229 vnf
['description']=vnf_db
[0]['description']
1230 #get external interfaces
1231 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1232 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1233 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1234 for ext_iface
in ext_ifaces
:
1235 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1237 #1.4 get list of connections
1238 conections
= topo
['topology']['connections']
1239 conections_list
= []
1240 conections_list_name
= []
1241 for k
in conections
.keys():
1242 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1243 ifaces_list
= conections
[k
]['nodes'].items()
1244 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1246 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1247 for k2
in conection_pair_list
:
1250 con_type
= conections
[k
].get("type", "link")
1251 if con_type
!= "link":
1253 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1254 other_nets
[k
] = {'external': False}
1255 if conections
[k
].get("graph"):
1256 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1257 ifaces_list
.append( (k
, None) )
1260 if con_type
== "external_network":
1261 other_nets
[k
]['external'] = True
1262 if conections
[k
].get("model"):
1263 other_nets
[k
]["model"] = conections
[k
]["model"]
1265 other_nets
[k
]["model"] = k
1266 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1267 other_nets
[k
]["model"] = con_type
1269 conections_list_name
.append(k
)
1270 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)
1271 #print set(ifaces_list)
1272 #check valid VNF and iface names
1273 for iface
in ifaces_list
:
1274 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1275 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1276 str(k
), iface
[0]), HTTP_Not_Found
)
1277 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1278 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1279 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1281 #1.5 unify connections from the pair list to a consolidated list
1283 while index
< len(conections_list
):
1285 while index2
< len(conections_list
):
1286 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1287 conections_list
[index
] |
= conections_list
[index2
]
1288 del conections_list
[index2
]
1289 del conections_list_name
[index2
]
1292 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1294 #for k in conections_list:
1299 #1.6 Delete non external nets
1300 # for k in other_nets.keys():
1301 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1302 # for con in conections_list:
1304 # for index in range(0,len(con)):
1305 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1306 # for index in delete_indexes:
1309 #1.7: Check external_ports are present at database table datacenter_nets
1310 for k
,net
in other_nets
.items():
1311 error_pos
= "'topology':'nodes':'" + k
+ "'"
1312 if net
['external']==False:
1313 if 'name' not in net
:
1315 if 'model' not in net
:
1316 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1317 if net
['model']=='bridge_net':
1318 net
['type']='bridge';
1319 elif net
['model']=='dataplane_net':
1322 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1324 #IF we do not want to check that external network exist at datacenter
1329 # if 'net_id' in net:
1330 # error_text += " 'net_id' " + net['net_id']
1331 # WHERE_['uuid'] = net['net_id']
1332 # if 'model' in net:
1333 # error_text += " 'model' " + net['model']
1334 # WHERE_['name'] = net['model']
1335 # if len(WHERE_) == 0:
1336 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1337 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1338 # FROM='datacenter_nets', WHERE=WHERE_ )
1340 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1342 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1343 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1345 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1346 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1347 # other_nets[k].update(net_db[0])
1350 net_nb
=0 #Number of nets
1351 for con
in conections_list
:
1352 #check if this is connected to a external net
1356 for index
in range(0,len(con
)):
1357 #check if this is connected to a external net
1358 for net_key
in other_nets
.keys():
1359 if con
[index
][0]==net_key
:
1360 if other_net_index
>=0:
1361 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1362 #print "nfvo.new_scenario " + error_text
1363 raise NfvoException(error_text
, HTTP_Bad_Request
)
1365 other_net_index
= index
1366 net_target
= net_key
1368 #print "other_net_index", other_net_index
1370 if other_net_index
>=0:
1371 del con
[other_net_index
]
1372 #IF we do not want to check that external network exist at datacenter
1373 if other_nets
[net_target
]['external'] :
1374 if "name" not in other_nets
[net_target
]:
1375 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1376 if other_nets
[net_target
]["type"] == "external_network":
1377 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1378 other_nets
[net_target
]["type"] = "data"
1380 other_nets
[net_target
]["type"] = "bridge"
1382 # if other_nets[net_target]['external'] :
1383 # 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
1384 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1385 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1386 # print "nfvo.new_scenario " + error_text
1387 # return -HTTP_Bad_Request, error_text
1390 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1393 net_type_bridge
=False
1395 net_target
= "__-__net"+str(net_nb
)
1396 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1397 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1400 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1401 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1402 if iface_type
=='mgmt' or iface_type
=='bridge':
1403 net_type_bridge
= True
1405 net_type_data
= True
1406 if net_type_bridge
and net_type_data
:
1407 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1408 #print "nfvo.new_scenario " + error_text
1409 raise NfvoException(error_text
, HTTP_Bad_Request
)
1410 elif net_type_bridge
:
1413 type_
='data' if len(con
)>2 else 'ptp'
1414 net_list
[net_target
]['type'] = type_
1417 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1418 #print "nfvo.new_scenario " + error_text
1420 raise NfvoException(error_text
, HTTP_Bad_Request
)
1422 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1423 #1.8.1 obtain management net
1424 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1425 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1426 #1.8.2 check all interfaces from all vnfs
1428 add_mgmt_net
= False
1429 for vnf
in vnfs
.values():
1430 for iface
in vnf
['ifaces'].values():
1431 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1432 #iface not connected
1433 iface
['net_key'] = 'mgmt'
1435 if add_mgmt_net
and 'mgmt' not in net_list
:
1436 net_list
['mgmt']=mgmt_net
[0]
1437 net_list
['mgmt']['external']=True
1438 net_list
['mgmt']['graph']={'visible':False}
1440 net_list
.update(other_nets
)
1442 #print 'net_list', net_list
1447 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1448 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1449 'tenant_id':tenant_id
, 'name':topo
['name'],
1450 'description':topo
.get('description',topo
['name']),
1451 'public': topo
.get('public', False)
1457 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
1458 """ This creates a new scenario for version 0.2 and 0.3"""
1459 scenario
= scenario_dict
["scenario"]
1460 if tenant_id
!= "any":
1461 check_tenant(mydb
, tenant_id
)
1462 if "tenant_id" in scenario
:
1463 if scenario
["tenant_id"] != tenant_id
:
1464 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1465 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1466 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1470 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
1471 for name
,vnf
in scenario
["vnfs"].iteritems():
1473 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1475 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1477 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1478 where
['uuid'] = vnf
['vnf_id']
1479 if 'vnf_name' in vnf
:
1480 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1481 where
['name'] = vnf
['vnf_name']
1483 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1484 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
1489 if len(vnf_db
) == 0:
1490 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1491 elif len(vnf_db
) > 1:
1492 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1493 vnf
['uuid'] = vnf_db
[0]['uuid']
1494 vnf
['description'] = vnf_db
[0]['description']
1496 # get external interfaces
1497 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
1498 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1499 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name': None} )
1500 for ext_iface
in ext_ifaces
:
1501 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
1502 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1504 # 2: Insert net_key and ip_address at every vnf interface
1505 for net_name
, net
in scenario
["networks"].items():
1506 net_type_bridge
= False
1507 net_type_data
= False
1508 for iface_dict
in net
["interfaces"]:
1509 if version
== "0.2":
1510 temp_dict
= iface_dict
1512 elif version
== "0.3":
1513 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
1514 ip_address
= iface_dict
.get('ip_address', None)
1515 for vnf
, iface
in temp_dict
.items():
1516 if vnf
not in scenario
["vnfs"]:
1517 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
1519 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1520 raise NfvoException(error_text
, HTTP_Not_Found
)
1521 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1522 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
1523 .format(net_name
, iface
)
1524 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1525 raise NfvoException(error_text
, HTTP_Bad_Request
)
1526 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1527 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
1528 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1529 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1530 raise NfvoException(error_text
, HTTP_Bad_Request
)
1531 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1532 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
1533 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1534 if iface_type
== 'mgmt' or iface_type
== 'bridge':
1535 net_type_bridge
= True
1537 net_type_data
= True
1539 if net_type_bridge
and net_type_data
:
1540 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
1542 # logger.debug("nfvo.new_scenario " + error_text)
1543 raise NfvoException(error_text
, HTTP_Bad_Request
)
1544 elif net_type_bridge
:
1547 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
1549 if net
.get("implementation"): # for v0.3
1550 if type_
== "bridge" and net
["implementation"] == "underlay":
1551 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
1552 "'network':'{}'".format(net_name
)
1553 # logger.debug(error_text)
1554 raise NfvoException(error_text
, HTTP_Bad_Request
)
1555 elif type_
!= "bridge" and net
["implementation"] == "overlay":
1556 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
1557 "'network':'{}'".format(net_name
)
1558 # logger.debug(error_text)
1559 raise NfvoException(error_text
, HTTP_Bad_Request
)
1560 net
.pop("implementation")
1561 if "type" in net
and version
== "0.3": # for v0.3
1562 if type_
== "data" and net
["type"] == "e-line":
1563 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
1564 "'e-line' at 'network':'{}'".format(net_name
)
1565 # logger.debug(error_text)
1566 raise NfvoException(error_text
, HTTP_Bad_Request
)
1567 elif type_
== "ptp" and net
["type"] == "e-lan":
1571 net
['name'] = net_name
1572 net
['external'] = net
.get('external', False)
1574 # 3: insert at database
1575 scenario
["nets"] = scenario
["networks"]
1576 scenario
['tenant_id'] = tenant_id
1577 scenario_id
= mydb
.new_scenario(scenario
)
1581 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1582 data
["uuid"] = scenario_id
1583 data
["tenant_id"] = tenant_id
1584 c
= mydb
.edit_scenario( data
)
1588 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1589 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1590 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
1591 vims
= {datacenter_id
: myvim
}
1592 myvim_tenant
= myvim
['tenant_id']
1593 datacenter_name
= myvim
['name']
1597 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1598 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1599 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
1600 scenarioDict
['datacenter_id'] = datacenter_id
1601 #print '================scenarioDict======================='
1602 #print json.dumps(scenarioDict, indent=4)
1603 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1605 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1606 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1608 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1609 auxNetDict
['scenario'] = {}
1611 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1612 for sce_net
in scenarioDict
['nets']:
1613 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1615 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1616 myNetName
= myNetName
[0:255] #limit length
1617 myNetType
= sce_net
['type']
1619 myNetDict
["name"] = myNetName
1620 myNetDict
["type"] = myNetType
1621 myNetDict
["tenant_id"] = myvim_tenant
1622 myNetIPProfile
= sce_net
.get('ip_profile', None)
1624 #We should use the dictionary as input parameter for new_network
1626 if not sce_net
["external"]:
1627 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1628 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1629 sce_net
['vim_id'] = network_id
1630 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1631 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1632 sce_net
["created"] = True
1634 if sce_net
['vim_id'] == None:
1635 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1636 _
, message
= rollback(mydb
, vims
, rollbackList
)
1637 logger
.error("nfvo.start_scenario: %s", error_text
)
1638 raise NfvoException(error_text
, HTTP_Bad_Request
)
1639 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1640 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1642 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1643 #For each vnf net, we create it and we add it to instanceNetlist.
1644 for sce_vnf
in scenarioDict
['vnfs']:
1645 for net
in sce_vnf
['nets']:
1646 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1648 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1649 myNetName
= myNetName
[0:255] #limit length
1650 myNetType
= net
['type']
1652 myNetDict
["name"] = myNetName
1653 myNetDict
["type"] = myNetType
1654 myNetDict
["tenant_id"] = myvim_tenant
1655 myNetIPProfile
= net
.get('ip_profile', None)
1658 #We should use the dictionary as input parameter for new_network
1659 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1660 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1661 net
['vim_id'] = network_id
1662 if sce_vnf
['uuid'] not in auxNetDict
:
1663 auxNetDict
[sce_vnf
['uuid']] = {}
1664 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1665 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1666 net
["created"] = True
1668 #print "auxNetDict:"
1669 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1671 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1672 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1674 for sce_vnf
in scenarioDict
['vnfs']:
1675 for vm
in sce_vnf
['vms']:
1678 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1679 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
1680 #myVMDict['description'] = vm['description']
1681 myVMDict
['description'] = myVMDict
['name'][0:99]
1683 myVMDict
['start'] = "no"
1684 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1685 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1687 #create image at vim in case it not exist
1688 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1689 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1690 vm
['vim_image_id'] = image_id
1692 #create flavor at vim in case it not exist
1693 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1694 if flavor_dict
['extended']!=None:
1695 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1696 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1697 vm
['vim_flavor_id'] = flavor_id
1700 myVMDict
['imageRef'] = vm
['vim_image_id']
1701 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1702 myVMDict
['networks'] = []
1703 for iface
in vm
['interfaces']:
1705 if iface
['type']=="data":
1706 netDict
['type'] = iface
['model']
1707 elif "model" in iface
and iface
["model"]!=None:
1708 netDict
['model']=iface
['model']
1709 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1710 #discover type of interface looking at flavor
1711 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1712 for flavor_iface
in numa
.get('interfaces',[]):
1713 if flavor_iface
.get('name') == iface
['internal_name']:
1714 if flavor_iface
['dedicated'] == 'yes':
1715 netDict
['type']="PF" #passthrough
1716 elif flavor_iface
['dedicated'] == 'no':
1717 netDict
['type']="VF" #siov
1718 elif flavor_iface
['dedicated'] == 'yes:sriov':
1719 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1720 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1722 netDict
["use"]=iface
['type']
1723 if netDict
["use"]=="data" and not netDict
.get("type"):
1724 #print "netDict", netDict
1725 #print "iface", iface
1726 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'])
1727 if flavor_dict
.get('extended')==None:
1728 raise NfvoException(e_text
+ "After database migration some information is not available. \
1729 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1731 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1732 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1733 netDict
["type"]="virtual"
1734 if "vpci" in iface
and iface
["vpci"] is not None:
1735 netDict
['vpci'] = iface
['vpci']
1736 if "mac" in iface
and iface
["mac"] is not None:
1737 netDict
['mac_address'] = iface
['mac']
1738 if "port-security" in iface
and iface
["port-security"] is not None:
1739 netDict
['port_security'] = iface
['port-security']
1740 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
1741 netDict
['floating_ip'] = iface
['floating-ip']
1742 netDict
['name'] = iface
['internal_name']
1743 if iface
['net_id'] is None:
1744 for vnf_iface
in sce_vnf
["interfaces"]:
1747 if vnf_iface
['interface_id']==iface
['uuid']:
1748 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1751 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1752 #skip bridge ifaces not connected to any net
1753 #if 'net_id' not in netDict or netDict['net_id']==None:
1755 myVMDict
['networks'].append(netDict
)
1756 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1757 #print myVMDict['name']
1758 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1759 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1760 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1761 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1762 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1763 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1764 vm
['vim_id'] = vm_id
1765 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1766 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1767 for net
in myVMDict
['networks']:
1769 for iface
in vm
['interfaces']:
1770 if net
["name"]==iface
["internal_name"]:
1771 iface
["vim_id"]=net
["vim_id"]
1774 logger
.debug("start scenario Deployment done")
1775 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1776 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1777 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1778 return mydb
.get_instance_scenario(instance_id
)
1780 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1781 _
, message
= rollback(mydb
, vims
, rollbackList
)
1782 if isinstance(e
, db_base_Exception
):
1783 error_text
= "Exception at database"
1785 error_text
= "Exception at VIM"
1786 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1787 #logger.error("start_scenario %s", error_text)
1788 raise NfvoException(error_text
, e
.http_code
)
1791 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
1792 ''' join the cloud config information into cloud_config_preserve.
1793 In case of conflict cloud_config_preserve preserves
1796 if not cloud_config_preserve
and not cloud_config
:
1799 new_cloud_config
= {"key-pairs":[], "users":[]}
1801 if cloud_config_preserve
:
1802 for key
in cloud_config_preserve
.get("key-pairs", () ):
1803 if key
not in new_cloud_config
["key-pairs"]:
1804 new_cloud_config
["key-pairs"].append(key
)
1806 for key
in cloud_config
.get("key-pairs", () ):
1807 if key
not in new_cloud_config
["key-pairs"]:
1808 new_cloud_config
["key-pairs"].append(key
)
1809 if not new_cloud_config
["key-pairs"]:
1810 del new_cloud_config
["key-pairs"]
1814 new_cloud_config
["users"] += cloud_config
.get("users", () )
1815 if cloud_config_preserve
:
1816 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
1817 index_to_delete
= []
1818 users
= new_cloud_config
.get("users", [])
1819 for index0
in range(0,len(users
)):
1820 if index0
in index_to_delete
:
1822 for index1
in range(index0
+1,len(users
)):
1823 if index1
in index_to_delete
:
1825 if users
[index0
]["name"] == users
[index1
]["name"]:
1826 index_to_delete
.append(index1
)
1827 for key
in users
[index1
].get("key-pairs",()):
1828 if "key-pairs" not in users
[index0
]:
1829 users
[index0
]["key-pairs"] = [key
]
1830 elif key
not in users
[index0
]["key-pairs"]:
1831 users
[index0
]["key-pairs"].append(key
)
1832 index_to_delete
.sort(reverse
=True)
1833 for index
in index_to_delete
:
1835 if not new_cloud_config
["users"]:
1836 del new_cloud_config
["users"]
1839 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
1840 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
1841 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
1842 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
1845 if cloud_config
and cloud_config
.get("user-data") != None:
1846 new_cloud_config
["user-data"] = cloud_config
["user-data"]
1847 if cloud_config_preserve
and cloud_config_preserve
.get("user-data") != None:
1848 new_cloud_config
["user-data"] = cloud_config_preserve
["user-data"]
1851 new_cloud_config
["config-files"] = []
1852 if cloud_config
and cloud_config
.get("config-files") != None:
1853 new_cloud_config
["config-files"] += cloud_config
["config-files"]
1854 if cloud_config_preserve
:
1855 for file in cloud_config_preserve
.get("config-files", ()):
1856 for index
in range(0, len(new_cloud_config
["config-files"])):
1857 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
1858 new_cloud_config
["config-files"][index
] = file
1861 new_cloud_config
["config-files"].append(file)
1862 if not new_cloud_config
["config-files"]:
1863 del new_cloud_config
["config-files"]
1864 return new_cloud_config
1867 def get_vim_thread(tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
1868 datacenter_id
= None
1869 datacenter_name
= None
1871 if datacenter_id_name
:
1872 if utils
.check_valid_uuid(datacenter_id_name
):
1873 datacenter_id
= datacenter_id_name
1875 datacenter_name
= datacenter_id_name
1877 thread
= vim_threads
["running"].get(datacenter_id
+ "." + tenant_id
)
1879 for k
, v
in vim_threads
["running"].items():
1880 datacenter_tenant
= k
.split(".")
1881 if datacenter_tenant
[0] == datacenter_id
and datacenter_tenant
[1] == tenant_id
:
1883 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1885 elif not datacenter_id
and datacenter_tenant
[1] == tenant_id
:
1886 if thread
.datacenter_name
== datacenter_name
:
1888 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1891 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1895 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1896 datacenter_id
= None
1897 datacenter_name
= None
1898 if datacenter_id_name
:
1899 if utils
.check_valid_uuid(datacenter_id_name
):
1900 datacenter_id
= datacenter_id_name
1902 datacenter_name
= datacenter_id_name
1903 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1905 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1907 #print "nfvo.datacenter_action() error. Several datacenters found"
1908 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1909 return vims
.keys()[0], vims
.values()[0]
1913 '''Takes dict d and updates it with the values in dict u.'''
1914 '''It merges all depth levels'''
1915 for k
, v
in u
.iteritems():
1916 if isinstance(v
, collections
.Mapping
):
1917 r
= update(d
.get(k
, {}), v
)
1924 def create_instance(mydb
, tenant_id
, instance_dict
):
1925 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1926 # logger.debug("Creating instance...")
1927 scenario
= instance_dict
["scenario"]
1929 #find main datacenter
1932 datacenter2tenant
= {}
1933 datacenter
= instance_dict
.get("datacenter")
1934 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1935 myvims
[default_datacenter_id
] = vim
1936 myvim_threads
[default_datacenter_id
] = get_vim_thread(tenant_id
, default_datacenter_id
)
1937 datacenter2tenant
[default_datacenter_id
] = vim
['config']['datacenter_tenant_id']
1938 #myvim_tenant = myvim['tenant_id']
1939 # default_datacenter_name = vim['name']
1942 #print "Checking that the scenario exists and getting the scenario dictionary"
1943 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1945 #logger.debug(">>>>>>> Dictionaries before merging")
1946 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1947 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1949 scenarioDict
['datacenter_id'] = default_datacenter_id
1951 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1952 auxNetDict
['scenario'] = {}
1954 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1955 instance_name
= instance_dict
["name"]
1956 instance_description
= instance_dict
.get("description")
1959 # 0 check correct parameters
1960 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1962 for scenario_net
in scenarioDict
['nets']:
1963 if net_name
== scenario_net
["name"]:
1967 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1968 if "sites" not in net_instance_desc
:
1969 net_instance_desc
["sites"] = [ {} ]
1970 site_without_datacenter_field
= False
1971 for site
in net_instance_desc
["sites"]:
1972 if site
.get("datacenter"):
1973 if site
["datacenter"] not in myvims
:
1974 #Add this datacenter to myvims
1975 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1977 myvim_threads
[d
] = get_vim_thread(tenant_id
, site
["datacenter"])
1978 datacenter2tenant
[d
] = v
['config']['datacenter_tenant_id']
1979 site
["datacenter"] = d
#change name to id
1981 if site_without_datacenter_field
:
1982 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1983 site_without_datacenter_field
= True
1984 site
["datacenter"] = default_datacenter_id
#change name to id
1986 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
1988 for scenario_vnf
in scenarioDict
['vnfs']:
1989 if vnf_name
== scenario_vnf
['name']:
1993 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
1994 if "datacenter" in vnf_instance_desc
:
1995 # Add this datacenter to myvims
1996 if vnf_instance_desc
["datacenter"] not in myvims
:
1997 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
1999 myvim_threads
[d
] = get_vim_thread(tenant_id
, vnf_instance_desc
["datacenter"])
2000 datacenter2tenant
[d
] = v
['config']['datacenter_tenant_id']
2001 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2003 #0.1 parse cloud-config parameters
2004 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2006 #0.2 merge instance information into scenario
2007 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2008 #However, this is not possible yet.
2009 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2010 for scenario_net
in scenarioDict
['nets']:
2011 if net_name
== scenario_net
["name"]:
2012 if 'ip-profile' in net_instance_desc
:
2013 ipprofile
= net_instance_desc
['ip-profile']
2014 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
2015 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
2016 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
2017 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
2018 if 'dhcp' in ipprofile
:
2019 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
2020 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
2021 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
2022 del ipprofile
['dhcp']
2023 if 'ip_profile' not in scenario_net
:
2024 scenario_net
['ip_profile'] = ipprofile
2026 update(scenario_net
['ip_profile'],ipprofile
)
2027 for interface
in net_instance_desc
.get('interfaces', () ):
2028 if 'ip_address' in interface
:
2029 for vnf
in scenarioDict
['vnfs']:
2030 if interface
['vnf'] == vnf
['name']:
2031 for vnf_interface
in vnf
['interfaces']:
2032 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2033 vnf_interface
['ip_address']=interface
['ip_address']
2035 #logger.debug(">>>>>>>> Merged dictionary")
2036 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
2039 # 1. Creating new nets (sce_nets) in the VIM"
2040 for sce_net
in scenarioDict
['nets']:
2041 sce_net
["vim_id_sites"]={}
2042 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
2043 net_name
= descriptor_net
.get("vim-network-name")
2044 auxNetDict
['scenario'][sce_net
['uuid']] = {}
2046 sites
= descriptor_net
.get("sites", [ {} ])
2048 if site
.get("datacenter"):
2049 vim
= myvims
[ site
["datacenter"] ]
2050 datacenter_id
= site
["datacenter"]
2051 myvim_thread
= myvim_threads
[ site
["datacenter"] ]
2053 vim
= myvims
[ default_datacenter_id
]
2054 datacenter_id
= default_datacenter_id
2055 myvim_thread
= myvim_threads
[default_datacenter_id
]
2056 net_type
= sce_net
['type']
2057 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
2058 if sce_net
["external"]:
2060 net_name
= sce_net
["name"]
2061 if "netmap-use" in site
or "netmap-create" in site
:
2062 create_network
= False
2063 lookfor_network
= False
2064 if "netmap-use" in site
:
2065 lookfor_network
= True
2066 if utils
.check_valid_uuid(site
["netmap-use"]):
2067 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2068 lookfor_filter
["id"] = site
["netmap-use"]
2070 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2071 lookfor_filter
["name"] = site
["netmap-use"]
2072 if "netmap-create" in site
:
2073 create_network
= True
2074 net_vim_name
= net_name
2075 if site
["netmap-create"]:
2076 net_vim_name
= site
["netmap-create"]
2078 elif sce_net
['vim_id'] != None:
2079 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
2080 create_network
= False
2081 lookfor_network
= True
2082 lookfor_filter
["id"] = sce_net
['vim_id']
2083 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
2084 #look for network at datacenter and return error
2086 #There is not a netmap, look at datacenter for a net with this name and create if not found
2087 create_network
= True
2088 lookfor_network
= True
2089 lookfor_filter
["name"] = sce_net
["name"]
2090 net_vim_name
= sce_net
["name"]
2091 filter_text
= "scenario name '%s'" % sce_net
["name"]
2094 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
2095 net_name
= net_name
[:255] #limit length
2096 net_vim_name
= net_name
2097 create_network
= True
2098 lookfor_network
= False
2101 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
2102 if len(vim_nets
) > 1:
2103 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2104 elif len(vim_nets
) == 0:
2105 if not create_network
:
2106 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2108 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
2109 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
2110 create_network
= False
2112 #if network is not external
2113 task
= new_task("new-net", (net_vim_name
, net_type
, sce_net
.get('ip_profile',None)))
2114 task_id
= myvim_thread
.insert_task(task
)
2115 instance_tasks
[task_id
] = task
2116 #network_id = vim.new_network(net_vim_name, net_type, sce_net.get('ip_profile',None))
2117 sce_net
["vim_id_sites"][datacenter_id
] = task_id
2118 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = task_id
2119 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':task_id
})
2120 sce_net
["created"] = True
2122 # 2. Creating new nets (vnf internal nets) in the VIM"
2123 #For each vnf net, we create it and we add it to instanceNetlist.
2124 for sce_vnf
in scenarioDict
['vnfs']:
2125 for net
in sce_vnf
['nets']:
2126 if sce_vnf
.get("datacenter"):
2127 vim
= myvims
[ sce_vnf
["datacenter"] ]
2128 datacenter_id
= sce_vnf
["datacenter"]
2129 myvim_thread
= myvim_threads
[ sce_vnf
["datacenter"]]
2131 vim
= myvims
[ default_datacenter_id
]
2132 datacenter_id
= default_datacenter_id
2133 myvim_thread
= myvim_threads
[default_datacenter_id
]
2134 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
2135 net_name
= descriptor_net
.get("name")
2137 net_name
= "%s.%s" %(instance_name
, net
["name"])
2138 net_name
= net_name
[:255] #limit length
2139 net_type
= net
['type']
2140 task
= new_task("new-net", (net_name
, net_type
, net
.get('ip_profile',None)))
2141 task_id
= myvim_thread
.insert_task(task
)
2142 instance_tasks
[task_id
] = task
2143 # network_id = vim.new_network(net_name, net_type, net.get('ip_profile',None))
2144 net
['vim_id'] = task_id
2145 if sce_vnf
['uuid'] not in auxNetDict
:
2146 auxNetDict
[sce_vnf
['uuid']] = {}
2147 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = task_id
2148 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':task_id
})
2149 net
["created"] = True
2152 #print "auxNetDict:"
2153 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2155 # 3. Creating new vm instances in the VIM
2156 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2157 for sce_vnf
in scenarioDict
['vnfs']:
2158 if sce_vnf
.get("datacenter"):
2159 vim
= myvims
[ sce_vnf
["datacenter"] ]
2160 myvim_thread
= myvim_threads
[ sce_vnf
["datacenter"] ]
2161 datacenter_id
= sce_vnf
["datacenter"]
2163 vim
= myvims
[ default_datacenter_id
]
2164 myvim_thread
= myvim_threads
[ default_datacenter_id
]
2165 datacenter_id
= default_datacenter_id
2166 sce_vnf
["datacenter_id"] = datacenter_id
2168 for vm
in sce_vnf
['vms']:
2171 myVMDict
['name'] = "{}.{}.{}".format(instance_name
,sce_vnf
['name'],chr(96+i
))
2172 myVMDict
['description'] = myVMDict
['name'][0:99]
2174 # myVMDict['start'] = "no"
2175 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2176 #create image at vim in case it not exist
2177 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2178 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2179 vm
['vim_image_id'] = image_id
2181 #create flavor at vim in case it not exist
2182 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2183 if flavor_dict
['extended']!=None:
2184 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2185 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
2187 #Obtain information for additional disks
2188 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
2189 if not extended_flavor_dict
:
2190 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
2193 #extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
2194 myVMDict
['disks'] = None
2195 extended_info
= extended_flavor_dict
[0]['extended']
2196 if extended_info
!= None:
2197 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
2198 if 'disks' in extended_flavor_dict_yaml
:
2199 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
2201 vm
['vim_flavor_id'] = flavor_id
2202 myVMDict
['imageRef'] = vm
['vim_image_id']
2203 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2204 myVMDict
['networks'] = []
2206 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
2207 for iface
in vm
['interfaces']:
2209 if iface
['type']=="data":
2210 netDict
['type'] = iface
['model']
2211 elif "model" in iface
and iface
["model"]!=None:
2212 netDict
['model']=iface
['model']
2213 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2214 #discover type of interface looking at flavor
2215 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2216 for flavor_iface
in numa
.get('interfaces',[]):
2217 if flavor_iface
.get('name') == iface
['internal_name']:
2218 if flavor_iface
['dedicated'] == 'yes':
2219 netDict
['type']="PF" #passthrough
2220 elif flavor_iface
['dedicated'] == 'no':
2221 netDict
['type']="VF" #siov
2222 elif flavor_iface
['dedicated'] == 'yes:sriov':
2223 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2224 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2226 netDict
["use"]=iface
['type']
2227 if netDict
["use"]=="data" and not netDict
.get("type"):
2228 #print "netDict", netDict
2229 #print "iface", iface
2230 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'])
2231 if flavor_dict
.get('extended')==None:
2232 raise NfvoException(e_text
+ "After database migration some information is not available. \
2233 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2235 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2236 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2237 netDict
["type"]="virtual"
2238 if "vpci" in iface
and iface
["vpci"] is not None:
2239 netDict
['vpci'] = iface
['vpci']
2240 if "mac" in iface
and iface
["mac"] is not None:
2241 netDict
['mac_address'] = iface
['mac']
2242 if "port-security" in iface
and iface
["port-security"] is not None:
2243 netDict
['port_security'] = iface
['port-security']
2244 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2245 netDict
['floating_ip'] = iface
['floating-ip']
2246 netDict
['name'] = iface
['internal_name']
2247 if iface
['net_id'] is None:
2248 for vnf_iface
in sce_vnf
["interfaces"]:
2251 if vnf_iface
['interface_id']==iface
['uuid']:
2252 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
2255 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2256 if is_task_id(netDict
['net_id']):
2257 task_depends
[netDict
['net_id']] = instance_tasks
[netDict
['net_id']]
2258 #skip bridge ifaces not connected to any net
2259 #if 'net_id' not in netDict or netDict['net_id']==None:
2261 myVMDict
['networks'].append(netDict
)
2262 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2263 #print myVMDict['name']
2264 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2265 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2266 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2267 if vm
.get("boot_data"):
2268 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
2270 cloud_config_vm
= cloud_config
2271 task
= new_task("new-vm", (myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2272 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2273 cloud_config_vm
, myVMDict
['disks']), depends
=task_depends
)
2274 vm_id
= myvim_thread
.insert_task(task
)
2275 instance_tasks
[vm_id
] = task
2277 vm
['vim_id'] = vm_id
2278 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2279 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2280 for net
in myVMDict
['networks']:
2282 for iface
in vm
['interfaces']:
2283 if net
["name"]==iface
["internal_name"]:
2284 iface
["vim_id"]=net
["vim_id"]
2286 scenarioDict
["datacenter2tenant"] = datacenter2tenant
2287 logger
.debug("create_instance Deployment done scenarioDict: %s",
2288 yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False) )
2289 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
2290 # Update database with those ended tasks
2291 for task
in instance_tasks
.values():
2292 if task
["status"] == "ok":
2293 if task
["name"] == "new-vm":
2294 mydb
.update_rows("instance_vms", UPDATE
={"vim_vm_id": task
["result"]},
2295 WHERE
={"vim_vm_id": task
["id"]})
2296 elif task
["name"] == "new-net":
2297 mydb
.update_rows("instance_nets", UPDATE
={"vim_net_id": task
["result"]},
2298 WHERE
={"vim_net_id": task
["id"]})
2299 return mydb
.get_instance_scenario(instance_id
)
2300 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2301 message
= rollback(mydb
, myvims
, rollbackList
)
2302 if isinstance(e
, db_base_Exception
):
2303 error_text
= "database Exception"
2304 elif isinstance(e
, vimconn
.vimconnException
):
2305 error_text
= "VIM Exception"
2307 error_text
= "Exception"
2308 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2309 #logger.error("create_instance: %s", error_text)
2310 raise NfvoException(error_text
, e
.http_code
)
2313 def delete_instance(mydb
, tenant_id
, instance_id
):
2314 #print "Checking that the instance_id exists and getting the instance dictionary"
2315 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2316 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2317 tenant_id
= instanceDict
["tenant_id"]
2318 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2320 #1. Delete from Database
2321 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2330 for sce_vnf
in instanceDict
['vnfs']:
2331 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2332 if datacenter_key
not in myvims
:
2334 myvim_thread
= get_vim_thread(tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2335 except NfvoException
as e
:
2336 logger
.error(str(e
))
2338 myvim_threads
[datacenter_key
] = myvim_thread
2339 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2340 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2342 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2343 sce_vnf
["datacenter_tenant_id"]))
2344 myvims
[datacenter_key
] = None
2346 myvims
[datacenter_key
] = vims
.values()[0]
2347 myvim
= myvims
[datacenter_key
]
2348 myvim_thread
= myvim_threads
[datacenter_key
]
2349 for vm
in sce_vnf
['vms']:
2351 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2355 if is_task_id(vm
['vim_vm_id']):
2356 task_id
= vm
['vim_vm_id']
2357 old_task
= task_dict
.get(task_id
)
2359 error_msg
+= "\n VM was scheduled for create, but task {} is not found".format(task_id
)
2362 if old_task
["status"] == "enqueued":
2363 old_task
["status"] = "deleted"
2364 elif old_task
["status"] == "error":
2366 elif old_task
["status"] == "processing":
2367 task
= new_task("del-vm", task_id
, depends
={task_id
: old_task
})
2369 task
= new_task("del-vm", old_task
["result"])
2371 task
= new_task("del-vm", vm
['vim_vm_id'], store
=False)
2373 myvim_thread
.insert_task(task
)
2374 except vimconn
.vimconnNotFoundException
as e
:
2375 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2376 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2377 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2378 except vimconn
.vimconnException
as e
:
2379 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2380 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2381 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2385 for net
in instanceDict
['nets']:
2386 if not net
['created']:
2387 continue #skip not created nets
2388 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2389 if datacenter_key
not in myvims
:
2391 myvim_thread
= get_vim_thread(tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2392 except NfvoException
as e
:
2393 logger
.error(str(e
))
2395 myvim_threads
[datacenter_key
] = myvim_thread
2396 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2397 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2399 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2400 myvims
[datacenter_key
] = None
2402 myvims
[datacenter_key
] = vims
.values()[0]
2403 myvim
= myvims
[datacenter_key
]
2404 myvim_thread
= myvim_threads
[datacenter_key
]
2407 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2411 if is_task_id(net
['vim_net_id']):
2412 task_id
= net
['vim_net_id']
2413 old_task
= task_dict
.get(task_id
)
2415 error_msg
+= "\n NET was scheduled for create, but task {} is not found".format(task_id
)
2418 if old_task
["status"] == "enqueued":
2419 old_task
["status"] = "deleted"
2420 elif old_task
["status"] == "error":
2422 elif old_task
["status"] == "processing":
2423 task
= new_task("del-net", task_id
, depends
={task_id
: old_task
})
2425 task
= new_task("del-net", old_task
["result"])
2427 task
= new_task("del-net", (net
['vim_net_id'], net
['sdn_net_id']), store
=False)
2429 myvim_thread
.insert_task(task
)
2430 except vimconn
.vimconnNotFoundException
as e
:
2431 error_msg
+= "\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2432 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2433 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2434 except vimconn
.vimconnException
as e
:
2435 error_msg
+= "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'],
2436 net
["datacenter_id"],
2437 e
.http_code
, str(e
))
2438 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2439 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2440 if len(error_msg
) > 0:
2441 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2443 return 'instance ' + message
+ ' deleted'
2446 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2447 '''Refreshes a scenario instance. It modifies instanceDict'''
2449 - 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
2452 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2453 #print "nfvo.refresh_instance begins"
2454 #print json.dumps(instanceDict, indent=4)
2456 #print "Getting the VIM URL and the VIM tenant_id"
2459 # 1. Getting VIM vm and net list
2460 vms_updated
= [] #List of VM instance uuids in openmano that were updated
2463 for sce_vnf
in instanceDict
['vnfs']:
2464 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2465 if datacenter_key
not in vm_list
:
2466 vm_list
[datacenter_key
] = []
2467 if datacenter_key
not in myvims
:
2468 vims
= get_vim(mydb
, nfvo_tenant
, datacenter_id
=sce_vnf
["datacenter_id"],
2469 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2471 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"]))
2472 myvims
[datacenter_key
] = None
2474 myvims
[datacenter_key
] = vims
.values()[0]
2475 for vm
in sce_vnf
['vms']:
2476 vm_list
[datacenter_key
].append(vm
['vim_vm_id'])
2477 vms_notupdated
.append(vm
["uuid"])
2479 nets_updated
= [] #List of VM instance uuids in openmano that were updated
2482 for net
in instanceDict
['nets']:
2483 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2484 if datacenter_key
not in net_list
:
2485 net_list
[datacenter_key
] = []
2486 if datacenter_key
not in myvims
:
2487 vims
= get_vim(mydb
, nfvo_tenant
, datacenter_id
=net
["datacenter_id"],
2488 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2490 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2491 myvims
[datacenter_key
] = None
2493 myvims
[datacenter_key
] = vims
.values()[0]
2495 net_list
[datacenter_key
].append(net
['vim_net_id'])
2496 nets_notupdated
.append(net
["uuid"])
2498 # 1. Getting the status of all VMs
2500 for datacenter_key
in myvims
:
2501 if not vm_list
.get(datacenter_key
):
2505 if not myvims
[datacenter_key
]:
2506 failed_message
= "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"])
2509 vm_dict
.update(myvims
[datacenter_key
].refresh_vms_status(vm_list
[datacenter_key
]) )
2511 except vimconn
.vimconnException
as e
:
2512 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
2513 failed_message
= str(e
)
2515 for vm
in vm_list
[datacenter_key
]:
2516 vm_dict
[vm
] = {'status': "VIM_ERROR", 'error_msg': failed_message
}
2518 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2519 for sce_vnf
in instanceDict
['vnfs']:
2520 for vm
in sce_vnf
['vms']:
2521 vm_id
= vm
['vim_vm_id']
2522 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
2523 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2524 has_mgmt_iface
= False
2525 for iface
in vm
["interfaces"]:
2526 if iface
["type"]=="mgmt":
2527 has_mgmt_iface
= True
2528 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
2529 vm_dict
[vm_id
]['status'] = "ACTIVE"
2530 if vm_dict
[vm_id
].get('error_msg') and len(vm_dict
[vm_id
]['error_msg']) >= 1024:
2531 vm_dict
[vm_id
]['error_msg'] = vm_dict
[vm_id
]['error_msg'][:516] + " ... " + vm_dict
[vm_id
]['error_msg'][-500:]
2532 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'):
2533 vm
['status'] = vm_dict
[vm_id
]['status']
2534 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
2535 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
2536 # 2.1. Update in openmano DB the VMs whose status changed
2538 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
2539 vms_notupdated
.remove(vm
["uuid"])
2541 vms_updated
.append(vm
["uuid"])
2542 except db_base_Exception
as e
:
2543 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2544 # 2.2. Update in openmano DB the interface VMs
2545 for interface
in interfaces
:
2546 #translate from vim_net_id to instance_net_id
2548 for net
in instanceDict
['nets']:
2549 if net
["vim_net_id"] == interface
["vim_net_id"]:
2550 network_id_list
.append(net
["uuid"])
2551 if not network_id_list
:
2553 del interface
["vim_net_id"]
2555 for network_id
in network_id_list
:
2556 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
2557 except db_base_Exception
as e
:
2558 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
2560 # 3. Getting the status of all nets
2562 for datacenter_key
in myvims
:
2563 if not net_list
.get(datacenter_key
):
2567 if not myvims
[datacenter_key
]:
2568 failed_message
= "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"])
2571 net_dict
.update(myvims
[datacenter_key
].refresh_nets_status(net_list
[datacenter_key
]) )
2573 except vimconn
.vimconnException
as e
:
2574 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
2575 failed_message
= str(e
)
2577 for net
in net_list
[datacenter_key
]:
2578 net_dict
[net
] = {'status': "VIM_ERROR", 'error_msg': failed_message
}
2580 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2581 # TODO: update nets inside a vnf
2582 for net
in instanceDict
['nets']:
2583 net_id
= net
['vim_net_id']
2584 if net_dict
[net_id
].get('error_msg') and len(net_dict
[net_id
]['error_msg']) >= 1024:
2585 net_dict
[net_id
]['error_msg'] = net_dict
[net_id
]['error_msg'][:516] + " ... " + net_dict
[vm_id
]['error_msg'][-500:]
2586 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'):
2587 net
['status'] = net_dict
[net_id
]['status']
2588 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
2589 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
2590 # 5.1. Update in openmano DB the nets whose status changed
2592 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
2593 nets_notupdated
.remove(net
["uuid"])
2595 nets_updated
.append(net
["uuid"])
2596 except db_base_Exception
as e
:
2597 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2599 # Returns appropriate output
2600 #print "nfvo.refresh_instance finishes"
2601 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2602 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
2603 instance_id
= instanceDict
['uuid']
2604 if len(vms_notupdated
)+len(nets_notupdated
)>0:
2605 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
2606 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
2608 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2611 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2612 #print "Checking that the instance_id exists and getting the instance dictionary"
2613 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2614 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2616 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2617 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2619 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2620 myvim
= vims
.values()[0]
2623 input_vnfs
= action_dict
.pop("vnfs", [])
2624 input_vms
= action_dict
.pop("vms", [])
2625 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2629 for sce_vnf
in instanceDict
['vnfs']:
2630 for vm
in sce_vnf
['vms']:
2631 if not action_over_all
:
2632 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2633 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2636 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2637 if "console" in action_dict
:
2638 if not global_config
["http_console_proxy"]:
2639 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2640 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2641 protocol
=data
["protocol"],
2642 ip
= data
["server"],
2643 port
= data
["port"],
2644 suffix
= data
["suffix"]),
2648 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2649 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2650 "description": "this console is only reachable by local interface",
2655 #print "console data", data
2657 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2658 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2659 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2660 protocol
=data
["protocol"],
2661 ip
= global_config
["http_console_host"],
2662 port
= console_thread
.port
,
2663 suffix
= data
["suffix"]),
2667 except NfvoException
as e
:
2668 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2672 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2674 except vimconn
.vimconnException
as e
:
2675 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2678 if vm_ok
==0: #all goes wrong
2684 def create_or_use_console_proxy_thread(console_server
, console_port
):
2685 #look for a non-used port
2686 console_thread_key
= console_server
+ ":" + str(console_port
)
2687 if console_thread_key
in global_config
["console_thread"]:
2688 #global_config["console_thread"][console_thread_key].start_timeout()
2689 return global_config
["console_thread"][console_thread_key
]
2691 for port
in global_config
["console_port_iterator"]():
2692 #print "create_or_use_console_proxy_thread() port:", port
2693 if port
in global_config
["console_ports"]:
2696 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2698 global_config
["console_thread"][console_thread_key
] = clithread
2699 global_config
["console_ports"][port
] = console_thread_key
2701 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2702 #port used, try with onoher
2704 except cli
.ConsoleProxyException
as e
:
2705 raise NfvoException(str(e
), HTTP_Bad_Request
)
2706 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2709 def check_tenant(mydb
, tenant_id
):
2710 '''check that tenant exists at database'''
2711 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2713 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2717 def new_tenant(mydb
, tenant_dict
):
2718 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2722 def delete_tenant(mydb
, tenant
):
2723 #get nfvo_tenant info
2725 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2726 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2727 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2730 def new_datacenter(mydb
, datacenter_descriptor
):
2731 if "config" in datacenter_descriptor
:
2732 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2733 #Check that datacenter-type is correct
2734 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2737 module
= "vimconn_" + datacenter_type
2738 module_info
= imp
.find_module(module
)
2739 except (IOError, ImportError):
2740 if module_info
and module_info
[0]:
2741 file.close(module_info
[0])
2742 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2744 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2745 return datacenter_id
2748 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2749 #obtain data, check that only one exist
2750 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2752 datacenter_id
= datacenter
['uuid']
2753 where
={'uuid': datacenter
['uuid']}
2754 if "config" in datacenter_descriptor
:
2755 if datacenter_descriptor
['config']!=None:
2757 new_config_dict
= datacenter_descriptor
["config"]
2760 for k
in new_config_dict
:
2761 if new_config_dict
[k
]==None:
2764 config_text
= datacenter
.get("config")
2767 config_dict
= yaml
.load(config_text
)
2768 config_dict
.update(new_config_dict
)
2772 except Exception as e
:
2773 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2774 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2775 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2776 return datacenter_id
2779 def delete_datacenter(mydb
, datacenter
):
2780 #get nfvo_tenant info
2781 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2782 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2783 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2786 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):
2787 #get datacenter info
2788 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2789 datacenter_name
= myvim
["name"]
2791 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
2793 # get nfvo_tenant info
2794 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2795 if vim_tenant_name
==None:
2796 vim_tenant_name
=tenant_dict
['name']
2798 #check that this association does not exist before
2799 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2800 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2801 if len(tenants_datacenters
)>0:
2802 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2804 vim_tenant_id_exist_atdb
=False
2805 if not create_vim_tenant
:
2806 where_
={"datacenter_id": datacenter_id
}
2807 if vim_tenant_id
!=None:
2808 where_
["vim_tenant_id"] = vim_tenant_id
2809 if vim_tenant_name
!=None:
2810 where_
["vim_tenant_name"] = vim_tenant_name
2811 #check if vim_tenant_id is already at database
2812 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2813 if len(datacenter_tenants_dict
)>=1:
2814 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2815 vim_tenant_id_exist_atdb
=True
2816 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2818 datacenter_tenants_dict
= {}
2819 #insert at table datacenter_tenants
2820 else: #if vim_tenant_id==None:
2821 #create tenant at VIM if not provided
2823 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2824 except vimconn
.vimconnException
as e
:
2825 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2826 datacenter_tenants_dict
= {}
2827 datacenter_tenants_dict
["created"]="true"
2829 #fill datacenter_tenants table
2830 if not vim_tenant_id_exist_atdb
:
2831 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2832 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2833 datacenter_tenants_dict
["user"] = vim_username
2834 datacenter_tenants_dict
["passwd"] = vim_password
2835 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2837 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
2838 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2839 datacenter_tenants_dict
["uuid"] = id_
2841 #fill tenants_datacenters table
2842 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2843 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2845 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
2846 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
2847 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, db
=db
, db_lock
=db_lock
, ovim
=ovim
)
2849 thread_id
= datacenter_id
+ "." + tenant_dict
['uuid']
2850 vim_threads
["running"][thread_id
] = new_thread
2851 return datacenter_id
2853 def edit_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
2854 #Obtain the data of this datacenter_tenant_id
2855 vim_data
= mydb
.get_rows(
2856 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
2857 "datacenter_tenants.passwd", "datacenter_tenants.config"),
2858 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
2859 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
2860 "tenants_datacenters.datacenter_id": datacenter_id
})
2862 logger
.debug(str(vim_data
))
2863 if len(vim_data
) < 1:
2864 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
2868 v
['config'] = yaml
.load(v
['config'])
2871 v
['vim_tenant_id'] = vim_tenant_id
2873 v
['vim_tenant_name'] = vim_tenant_name
2875 v
['user'] = vim_username
2877 v
['passwd'] = vim_password
2881 v
['config'].update(config
)
2883 logger
.debug(str(v
))
2884 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
2885 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
2886 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
2888 return datacenter_id
2890 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2891 #get datacenter info
2892 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2894 #get nfvo_tenant info
2895 if not tenant_id
or tenant_id
=="any":
2898 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2899 tenant_uuid
= tenant_dict
['uuid']
2901 #check that this association exist before
2902 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2904 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2905 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2906 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2907 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2909 #delete this association
2910 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2912 #get vim_tenant info and deletes
2914 for tenant_datacenter_item
in tenant_datacenter_list
:
2915 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2916 #try to delete vim:tenant
2918 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2919 if vim_tenant_dict
['created']=='true':
2920 #delete tenant at VIM if created by NFVO
2922 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2923 except vimconn
.vimconnException
as e
:
2924 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2925 logger
.warn(warning
)
2926 except db_base_Exception
as e
:
2927 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2928 pass # the error will be caused because dependencies, vim_tenant can not be deleted
2929 thread_id
= datacenter_id
+ "." + tenant_datacenter_item
["nfvo_tenant_id"]
2930 thread
= vim_threads
["running"][thread_id
]
2931 thread
.insert_task(new_task("exit", None, store
=False))
2932 vim_threads
["deleting"][thread_id
] = thread
2933 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2936 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2938 #get datacenter info
2939 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2941 if 'net-update' in action_dict
:
2943 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2945 except vimconn
.vimconnException
as e
:
2946 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2947 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2948 #update nets Change from VIM format to NFVO format
2951 net_nfvo
={'datacenter_id': datacenter_id
}
2952 net_nfvo
['name'] = net
['name']
2953 #net_nfvo['description']= net['name']
2954 net_nfvo
['vim_net_id'] = net
['id']
2955 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2956 net_nfvo
['shared'] = net
['shared']
2957 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2958 net_list
.append(net_nfvo
)
2959 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2960 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2962 elif 'net-edit' in action_dict
:
2963 net
= action_dict
['net-edit'].pop('net')
2964 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2965 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2966 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2968 elif 'net-delete' in action_dict
:
2969 net
= action_dict
['net-deelte'].get('net')
2970 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2971 result
= mydb
.delete_row(FROM
='datacenter_nets',
2972 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2976 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2979 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2980 #get datacenter info
2981 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2983 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2984 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2985 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2989 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2990 #get datacenter info
2991 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2994 action_dict
= action_dict
["netmap"]
2995 if 'vim_id' in action_dict
:
2996 filter_dict
["id"] = action_dict
['vim_id']
2997 if 'vim_name' in action_dict
:
2998 filter_dict
["name"] = action_dict
['vim_name']
3000 filter_dict
["shared"] = True
3003 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
3004 except vimconn
.vimconnException
as e
:
3005 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
3006 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3007 if len(vim_nets
)>1 and action_dict
:
3008 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
3009 elif len(vim_nets
)==0: # and action_dict:
3010 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
3012 for net
in vim_nets
:
3013 net_nfvo
={'datacenter_id': datacenter_id
}
3014 if action_dict
and "name" in action_dict
:
3015 net_nfvo
['name'] = action_dict
['name']
3017 net_nfvo
['name'] = net
['name']
3018 #net_nfvo['description']= net['name']
3019 net_nfvo
['vim_net_id'] = net
['id']
3020 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3021 net_nfvo
['shared'] = net
['shared']
3022 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3024 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
3025 net_nfvo
["status"] = "OK"
3026 net_nfvo
["uuid"] = net_id
3027 except db_base_Exception
as e
:
3031 net_nfvo
["status"] = "FAIL: " + str(e
)
3032 net_list
.append(net_nfvo
)
3036 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
3037 #get datacenter info
3038 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3041 if utils
.check_valid_uuid(name
):
3042 filter_dict
["id"] = name
3044 filter_dict
["name"] = name
3046 if item
=="networks":
3047 #filter_dict['tenant_id'] = myvim['tenant_id']
3048 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
3049 elif item
=="tenants":
3050 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
3051 elif item
== "images":
3052 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
3054 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3055 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
3056 if name
and len(content
)==1:
3057 return {item
[:-1]: content
[0]}
3058 elif name
and len(content
)==0:
3059 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
3062 return {item
: content
}
3063 except vimconn
.vimconnException
as e
:
3064 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
3065 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
3068 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
3069 #get datacenter info
3070 if tenant_id
== "any":
3073 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3075 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
3076 logger
.debug("vim_action_delete vim response: " + str(content
))
3077 items
= content
.values()[0]
3078 if type(items
)==list and len(items
)==0:
3079 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
3080 elif type(items
)==list and len(items
)>1:
3081 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
3082 else: # it is a dict
3083 item_id
= items
["id"]
3084 item_name
= str(items
.get("name"))
3087 if item
=="networks":
3088 content
= myvim
.delete_network(item_id
)
3089 elif item
=="tenants":
3090 content
= myvim
.delete_tenant(item_id
)
3091 elif item
== "images":
3092 content
= myvim
.delete_image(item_id
)
3094 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3095 except vimconn
.vimconnException
as e
:
3096 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
3097 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
3099 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
3102 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
3103 #get datacenter info
3104 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
3105 if tenant_id
== "any":
3107 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3109 if item
=="networks":
3110 net
= descriptor
["network"]
3111 net_name
= net
.pop("name")
3112 net_type
= net
.pop("type", "bridge")
3113 net_public
= net
.pop("shared", False)
3114 net_ipprofile
= net
.pop("ip_profile", None)
3115 net_vlan
= net
.pop("vlan", None)
3116 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
3117 elif item
=="tenants":
3118 tenant
= descriptor
["tenant"]
3119 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
3121 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3122 except vimconn
.vimconnException
as e
:
3123 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
3125 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
3127 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
3128 #data = ovim.new_of_controller(sdn_controller)
3130 logger
.debug('New SDN controller created with uuid {}'.format(data
))
3133 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
3134 #data = ovim.edit_of_controller(controller_id, sdn_controller)
3136 msg
= 'SDN controller {} updated'.format(data
)
3140 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
3141 if controller_id
== None:
3142 #data = ovim.get_of_controllers()
3145 #data = ovim.show_of_controller(controller_id)
3146 data
= {'dpid': None}
3147 msg
= 'SDN controller list:\n {}'.format(data
)
3151 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
3152 select_
= ('uuid', 'config')
3153 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
3154 for datacenter
in datacenters
:
3155 if datacenter
['config']:
3156 config
= yaml
.load(datacenter
['config'])
3157 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
3158 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
3160 #data = ovim.delete_of_controller(controller_id)
3162 msg
= 'SDN controller {} deleted'.format(data
)
3166 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
3167 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
3168 if len(controller
) < 1:
3169 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
3172 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
3174 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
3176 #sdn_controller = ovim.show_of_controller(sdn_controller_id)
3177 #switch_dpid = sdn_controller["dpid"]
3180 for compute_node
in sdn_port_mapping
:
3181 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
3183 element
["compute_node"] = compute_node
["compute_node"]
3184 for port
in compute_node
["ports"]:
3185 element
["pci"] = port
.get("pci")
3186 element
["switch_port"] = port
.get("switch_port")
3187 element
["switch_mac"] = port
.get("switch_mac")
3188 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
3189 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
3190 " or 'switch_mac'", HTTP_Bad_Request
)
3191 maps
.append(dict(element
))
3193 #return ovim.set_of_port_mapping(maps, ofc_id=sdn_controller_id, switch_dpid=switch_dpid, region=datacenter_id)
3196 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
3197 #maps = ovim.get_of_port_mappings(db_filter={"region": datacenter_id})
3201 "sdn-controller": None,
3202 "datacenter-id": datacenter_id
,
3204 "ports_mapping": list()
3207 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
3208 if datacenter
['config']:
3209 config
= yaml
.load(datacenter
['config'])
3210 if 'sdn-controller' in config
:
3211 controller_id
= config
['sdn-controller']
3212 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
3213 result
["sdn-controller"] = controller_id
3214 result
["dpid"] = sdn_controller
["dpid"]
3216 # if result["sdn-controller"] == None or result["dpid"] == None:
3217 # raise NfvoException("Not all SDN controller information for datacenter {} could be found: {}".format(datacenter_id, result),
3218 # HTTP_Internal_Server_Error)
3223 ports_correspondence_dict
= dict()
3225 if result
["sdn-controller"] != link
["ofc_id"]:
3226 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
3227 if result
["dpid"] != link
["switch_dpid"]:
3228 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
3230 element
["pci"] = link
["pci"]
3231 if link
["switch_port"]:
3232 element
["switch_port"] = link
["switch_port"]
3233 if link
["switch_mac"]:
3234 element
["switch_mac"] = link
["switch_mac"]
3236 if not link
["compute_node"] in ports_correspondence_dict
:
3238 content
["compute_node"] = link
["compute_node"]
3239 content
["ports"] = list()
3240 ports_correspondence_dict
[link
["compute_node"]] = content
3242 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
3244 for key
in sorted(ports_correspondence_dict
):
3245 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
3249 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
3250 #return ovim.clear_of_port_mapping(db_filter={"region":datacenter_id})