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 from lib_osm_openvim
import ovim
as ovim_module
47 from lib_osm_openvim
.ovim
import ovimException
50 global vimconn_imported
52 global default_volume_size
53 default_volume_size
= '5' #size in GB
58 vimconn_imported
= {} # dictionary with VIM type as key, loaded module as value
59 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
60 vim_persistent_info
= {}
61 logger
= logging
.getLogger('openmano.nfvo')
63 global_instance_tasks
= {}
68 class NfvoException(Exception):
69 def __init__(self
, message
, http_code
):
70 self
.http_code
= http_code
71 Exception.__init
__(self
, message
)
77 if task_id
<= last_task_id
:
78 task_id
= last_task_id
+ 0.000001
79 last_task_id
= task_id
80 return "TASK.{:.6f}".format(task_id
)
83 def new_task(name
, params
, depends
=None):
84 task_id
= get_task_id()
85 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
87 task
["depends"] = depends
92 return True if id[:5] == "TASK." else False
95 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
96 name
= datacenter_name
[:16]
97 if name
not in vim_threads
["names"]:
98 vim_threads
["names"].append(name
)
100 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
101 if name
not in vim_threads
["names"]:
102 vim_threads
["names"].append(name
)
104 name
= datacenter_id
+ "-" + tenant_id
105 vim_threads
["names"].append(name
)
109 def start_service(mydb
):
110 global db
, global_config
111 db
= nfvo_db
.nfvo_db()
112 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
115 # Initialize openvim for SDN control
116 # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
117 # TODO: review ovim.py to delete not needed configuration
118 ovim_configuration
= {
119 'logger_name': 'openmano.ovim',
120 'network_vlan_range_start': 1000,
121 'network_vlan_range_end': 4096,
122 'db_name': global_config
["db_ovim_name"],
123 'db_host': global_config
["db_ovim_host"],
124 'db_user': global_config
["db_ovim_user"],
125 'db_passwd': global_config
["db_ovim_passwd"],
128 'network_type': 'bridge',
129 #TODO: log_level_of should not be needed. To be modified in ovim
130 'log_level_of': 'DEBUG'
133 ovim
= ovim_module
.ovim(ovim_configuration
)
136 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\
137 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
138 select_
= ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin',
139 'd.name as datacenter_name', 'dt.uuid as datacenter_tenant_id',
140 'dt.vim_tenant_name as vim_tenant_name', 'dt.vim_tenant_id as vim_tenant_id',
141 'user', 'passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
142 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
144 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
145 'datacenter_id': vim
.get('datacenter_id')}
147 extra
.update(yaml
.load(vim
["config"]))
148 if vim
.get('dt_config'):
149 extra
.update(yaml
.load(vim
["dt_config"]))
150 if vim
["type"] not in vimconn_imported
:
153 module
= "vimconn_" + vim
["type"]
154 pkg
= __import__("osm_ro." + module
)
155 vim_conn
= getattr(pkg
, module
)
156 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
157 # vim_conn = imp.load_module(vim["type"], *module_info)
158 vimconn_imported
[vim
["type"]] = vim_conn
159 except (IOError, ImportError) as e
:
160 # if module_info and module_info[0]:
161 # file.close(module_info[0])
162 raise NfvoException("Unknown vim type '{}'. Cannot open file '{}.py'; {}: {}".format(
163 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
165 thread_id
= vim
['datacenter_tenant_id']
166 vim_persistent_info
[thread_id
] = {}
169 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
170 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
171 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
172 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
173 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
174 user
=vim
['user'], passwd
=vim
['passwd'],
175 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
177 except Exception as e
:
178 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, e
),
179 HTTP_Internal_Server_Error
)
180 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['vim_tenant_id'], vim
['vim_tenant_name'],
181 vim
['vim_tenant_id'])
182 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, vim
['datacenter_name'],
183 vim
['datacenter_tenant_id'], db
=db
, db_lock
=db_lock
, ovim
=ovim
)
185 vim_threads
["running"][thread_id
] = new_thread
186 except db_base_Exception
as e
:
187 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
188 except ovim_module
.ovimException
as e
:
190 if message
[:22] == "DATABASE wrong version":
191 message
= "DATABASE wrong version of lib_osm_openvim {msg} -d{dbname} -u{dbuser} -p{dbpass} {ver}' "\
192 "at host {dbhost}".format(
193 msg
=message
[22:-3], dbname
=global_config
["db_ovim_name"],
194 dbuser
=global_config
["db_ovim_user"], dbpass
=global_config
["db_ovim_passwd"],
195 ver
=message
[-3:-1], dbhost
=global_config
["db_ovim_host"])
196 raise NfvoException(message
, HTTP_Bad_Request
)
200 global ovim
, global_config
203 for thread_id
,thread
in vim_threads
["running"].items():
204 thread
.insert_task(new_task("exit", None))
205 vim_threads
["deleting"][thread_id
] = thread
206 vim_threads
["running"] = {}
207 if global_config
and global_config
.get("console_thread"):
208 for thread
in global_config
["console_thread"]:
209 thread
.terminate
= True
212 return ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config
["version"],
213 global_config
["version_date"] ))
216 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
218 return result, content:
219 <0, error_text upon error
220 nb_records, flavor_list on success
223 WHERE_dict
['vnf_id'] = vnf_id
224 if nfvo_tenant
is not None:
225 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
227 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
228 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
229 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
230 #print "get_flavor_list result:", result
231 #print "get_flavor_list content:", content
233 for flavor
in flavors
:
234 flavorList
.append(flavor
['flavor_id'])
238 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
240 return result, content:
241 <0, error_text upon error
242 nb_records, flavor_list on success
245 WHERE_dict
['vnf_id'] = vnf_id
246 if nfvo_tenant
is not None:
247 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
249 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
250 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
253 imageList
.append(image
['image_id'])
257 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
258 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
259 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
260 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
261 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
262 raise exception upon error
265 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
266 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
267 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
268 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
269 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
270 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
271 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
272 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'
273 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
274 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
275 'user','passwd', 'dt.config as dt_config')
277 from_
= 'datacenters as d'
278 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
280 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
283 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
284 'datacenter_id': vim
.get('datacenter_id')}
286 extra
.update(yaml
.load(vim
["config"]))
287 if vim
.get('dt_config'):
288 extra
.update(yaml
.load(vim
["dt_config"]))
289 if vim
["type"] not in vimconn_imported
:
292 module
= "vimconn_" + vim
["type"]
293 pkg
= __import__("osm_ro." + module
)
294 vim_conn
= getattr(pkg
, module
)
295 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
296 # vim_conn = imp.load_module(vim["type"], *module_info)
297 vimconn_imported
[vim
["type"]] = vim_conn
298 except (IOError, ImportError) as e
:
299 # if module_info and module_info[0]:
300 # file.close(module_info[0])
301 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
302 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
305 if 'datacenter_tenant_id' in vim
:
306 thread_id
= vim
["datacenter_tenant_id"]
307 if thread_id
not in vim_persistent_info
:
308 vim_persistent_info
[thread_id
] = {}
309 persistent_info
= vim_persistent_info
[thread_id
]
313 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
314 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
315 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
316 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
317 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
318 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
319 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
320 config
=extra
, persistent_info
=persistent_info
322 except Exception as e
:
323 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
325 except db_base_Exception
as e
:
326 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
329 def rollback(mydb
, vims
, rollback_list
):
331 #delete things by reverse order
332 for i
in range(len(rollback_list
)-1, -1, -1):
333 item
= rollback_list
[i
]
334 if item
["where"]=="vim":
335 if item
["vim_id"] not in vims
:
337 if is_task_id(item
["uuid"]):
339 vim
= vims
[item
["vim_id"]]
341 if item
["what"]=="image":
342 vim
.delete_image(item
["uuid"])
343 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
344 elif item
["what"]=="flavor":
345 vim
.delete_flavor(item
["uuid"])
346 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
347 elif item
["what"]=="network":
348 vim
.delete_network(item
["uuid"])
349 elif item
["what"]=="vm":
350 vim
.delete_vminstance(item
["uuid"])
351 except vimconn
.vimconnException
as e
:
352 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
353 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
354 except db_base_Exception
as e
:
355 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
359 if item
["what"]=="image":
360 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
361 elif item
["what"]=="flavor":
362 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
363 except db_base_Exception
as e
:
364 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
365 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
366 if len(undeleted_items
)==0:
367 return True," Rollback successful."
369 return False," Rollback fails to delete: " + str(undeleted_items
)
372 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
374 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
376 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
378 #dataplane interfaces
379 for numa
in vnfc
.get("numas",() ):
380 for interface
in numa
.get("interfaces",()):
381 if interface
["name"] in name_dict
:
383 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
384 vnfc
["name"], interface
["name"]),
386 name_dict
[ interface
["name"] ] = "underlay"
388 for interface
in vnfc
.get("bridge-ifaces",() ):
389 if interface
["name"] in name_dict
:
391 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
392 vnfc
["name"], interface
["name"]),
394 name_dict
[ interface
["name"] ] = "overlay"
395 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
396 # check bood-data info
397 if "boot-data" in vnfc
:
398 # check that user-data is incompatible with users and config-files
399 if (vnfc
["boot-data"].get("users") or vnfc
["boot-data"].get("config-files")) and vnfc
["boot-data"].get("user-data"):
401 "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
404 #check if the info in external_connections matches with the one in the vnfcs
406 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
407 if external_connection
["name"] in name_list
:
409 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
410 external_connection
["name"]),
412 name_list
.append(external_connection
["name"])
413 if external_connection
["VNFC"] not in vnfc_interfaces
:
415 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
416 external_connection
["name"], external_connection
["VNFC"]),
419 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
421 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
422 external_connection
["name"],
423 external_connection
["local_iface_name"]),
426 #check if the info in internal_connections matches with the one in the vnfcs
428 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
429 if internal_connection
["name"] in name_list
:
431 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
432 internal_connection
["name"]),
434 name_list
.append(internal_connection
["name"])
435 #We should check that internal-connections of type "ptp" have only 2 elements
437 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
439 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
440 internal_connection
["name"],
441 'ptp' if vnf_descriptor_version
==1 else 'e-line',
442 'data' if vnf_descriptor_version
==1 else "e-lan"),
444 for port
in internal_connection
["elements"]:
446 iface
= port
["local_iface_name"]
447 if vnf
not in vnfc_interfaces
:
449 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
450 internal_connection
["name"], vnf
),
452 if iface
not in vnfc_interfaces
[ vnf
]:
454 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
455 internal_connection
["name"], iface
),
457 return -HTTP_Bad_Request
,
458 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
459 if vnfc_interfaces
[vnf
][iface
] == "overlay":
460 internal_connection
["type"] = "bridge"
462 internal_connection
["type"] = "data"
463 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
464 if vnfc_interfaces
[vnf
][iface
] == "overlay":
465 internal_connection
["implementation"] = "overlay"
467 internal_connection
["implementation"] = "underlay"
468 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
469 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
471 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
472 internal_connection
["name"],
473 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
474 'data' if vnf_descriptor_version
==1 else 'underlay'),
476 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
477 vnfc_interfaces
[vnf
][iface
] == "underlay":
479 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
480 internal_connection
["name"], iface
,
481 'data' if vnf_descriptor_version
==1 else 'underlay',
482 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
486 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=None):
488 if only_create_at_vim
:
489 image_mano_id
= image_dict
['uuid']
490 if return_on_error
== None:
491 return_on_error
= True
493 if image_dict
['location']:
494 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
496 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
498 image_mano_id
= images
[0]['uuid']
500 #create image in MANO DB
501 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
502 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
503 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
505 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
506 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
507 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
508 #create image at every vim
509 for vim_id
,vim
in vims
.iteritems():
510 image_created
="false"
512 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
513 #look at VIM if this image exist
515 if image_dict
['location'] is not None:
516 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
519 filter_dict
['name'] = image_dict
['universal_name']
520 if image_dict
.get('checksum') != None:
521 filter_dict
['checksum'] = image_dict
['checksum']
522 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
523 vim_images
= vim
.get_image_list(filter_dict
)
524 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
525 if len(vim_images
) > 1:
526 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), HTTP_Conflict
)
527 elif len(vim_images
) == 0:
528 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
530 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
531 image_vim_id
= vim_images
[0]['id']
533 except vimconn
.vimconnNotFoundException
as e
:
534 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
536 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
537 if image_dict
['location']:
538 image_vim_id
= vim
.new_image(image_dict
)
539 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
542 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
543 raise vimconn
.vimconnException(str(e
))
544 except vimconn
.vimconnException
as e
:
546 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
549 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
551 except vimconn
.vimconnException
as e
:
553 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
555 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
558 #if we reach here, the image has been created or existed
560 #add new vim_id at datacenters_images
561 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
562 elif image_db
[0]["vim_id"]!=image_vim_id
:
563 #modify existing vim_id at datacenters_images
564 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
566 return image_vim_id
if only_create_at_vim
else image_mano_id
569 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
570 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
571 'ram':flavor_dict
.get('ram'),
572 'vcpus':flavor_dict
.get('vcpus'),
574 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
575 del flavor_dict
['extended']
576 if 'extended' in flavor_dict
:
577 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
579 #look if flavor exist
580 if only_create_at_vim
:
581 flavor_mano_id
= flavor_dict
['uuid']
582 if return_on_error
== None:
583 return_on_error
= True
585 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
587 flavor_mano_id
= flavors
[0]['uuid']
590 #create one by one the images of aditional disks
591 dev_image_list
=[] #list of images
592 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
594 for device
in flavor_dict
['extended'].get('devices',[]):
595 if "image" not in device
and "image name" not in device
:
598 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
599 image_dict
['universal_name']=device
.get('image name')
600 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
601 image_dict
['location']=device
.get('image')
602 #image_dict['new_location']=vnfc.get('image location')
603 image_dict
['checksum']=device
.get('image checksum')
604 image_metadata_dict
= device
.get('image metadata', None)
605 image_metadata_str
= None
606 if image_metadata_dict
!= None:
607 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
608 image_dict
['metadata']=image_metadata_str
609 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
610 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
611 dev_image_list
.append(image_id
)
613 temp_flavor_dict
['name'] = flavor_dict
['name']
614 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
615 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
616 flavor_mano_id
= content
617 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
618 #create flavor at every vim
619 if 'uuid' in flavor_dict
:
620 del flavor_dict
['uuid']
622 for vim_id
,vim
in vims
.items():
623 flavor_created
="false"
625 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
626 #look at VIM if this flavor exist SKIPPED
627 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
629 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
633 #Create the flavor in VIM
634 #Translate images at devices from MANO id to VIM id
636 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
637 #make a copy of original devices
640 for device
in flavor_dict
["extended"].get("devices",[]):
643 devices_original
.append(dev
)
644 if 'image' in device
:
646 if 'image metadata' in device
:
647 del device
['image metadata']
649 for index
in range(0,len(devices_original
)) :
650 device
=devices_original
[index
]
651 if "image" not in device
and "image name" not in device
:
653 disk_list
.append({'size': device
.get('size', default_volume_size
)})
656 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
657 image_dict
['universal_name']=device
.get('image name')
658 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
659 image_dict
['location']=device
.get('image')
660 #image_dict['new_location']=device.get('image location')
661 image_dict
['checksum']=device
.get('image checksum')
662 image_metadata_dict
= device
.get('image metadata', None)
663 image_metadata_str
= None
664 if image_metadata_dict
!= None:
665 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
666 image_dict
['metadata']=image_metadata_str
667 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
668 image_dict
["uuid"]=image_mano_id
669 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
671 #save disk information (image must be based on and size
672 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
674 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
677 #check that this vim_id exist in VIM, if not create
678 flavor_vim_id
=flavor_db
[0]["vim_id"]
680 vim
.get_flavor(flavor_vim_id
)
681 continue #flavor exist
682 except vimconn
.vimconnException
:
684 #create flavor at vim
685 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
688 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
689 flavor_create
="false"
690 except vimconn
.vimconnException
as e
:
693 if not flavor_vim_id
:
694 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
695 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
696 flavor_created
="true"
697 except vimconn
.vimconnException
as e
:
699 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
701 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
704 #if reach here the flavor has been create or exist
705 if len(flavor_db
)==0:
706 #add new vim_id at datacenters_flavors
707 extended_devices_yaml
= None
708 if len(disk_list
) > 0:
709 extended_devices
= dict()
710 extended_devices
['disks'] = disk_list
711 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
712 mydb
.new_row('datacenters_flavors',
713 {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
,
714 'created':flavor_created
,'extended': extended_devices_yaml
})
715 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
716 #modify existing vim_id at datacenters_flavors
717 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
719 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
722 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
725 # Step 1. Check the VNF descriptor
726 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
727 # Step 2. Check tenant exist
729 if tenant_id
!= "any":
730 check_tenant(mydb
, tenant_id
)
731 if "tenant_id" in vnf_descriptor
["vnf"]:
732 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
733 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
736 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
737 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
738 if global_config
["auto_push_VNF_to_VIMs"]:
739 vims
= get_vim(mydb
, tenant_id
)
741 # Step 4. Review the descriptor and add missing fields
742 #print vnf_descriptor
743 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
744 vnf_name
= vnf_descriptor
['vnf']['name']
745 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
746 if "physical" in vnf_descriptor
['vnf']:
747 del vnf_descriptor
['vnf']['physical']
748 #print vnf_descriptor
750 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
751 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
752 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
754 #For each VNFC, we add it to the VNFCDict and we create a flavor.
755 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
756 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
758 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
759 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
761 VNFCitem
["name"] = vnfc
['name']
762 VNFCitem
["availability_zone"] = vnfc
.get('availability_zone')
763 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
765 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
768 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
769 myflavorDict
["description"] = VNFCitem
["description"]
770 myflavorDict
["ram"] = vnfc
.get("ram", 0)
771 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
772 myflavorDict
["disk"] = vnfc
.get("disk", 1)
773 myflavorDict
["extended"] = {}
775 devices
= vnfc
.get("devices")
777 myflavorDict
["extended"]["devices"] = devices
780 # 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
781 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
783 # Previous code has been commented
784 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
785 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
786 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
787 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
789 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
791 # print "Error creating flavor: unknown processor model. Rollback successful."
792 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
794 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
795 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
797 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
798 myflavorDict
['extended']['numas'] = vnfc
['numas']
802 # Step 6.2 New flavors are created in the VIM
803 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
805 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
806 VNFCitem
["flavor_id"] = flavor_id
807 VNFCDict
[vnfc
['name']] = VNFCitem
809 logger
.debug("Creating new images in the VIM for each VNFC")
810 # Step 6.3 New images are created in the VIM
811 #For each VNFC, we must create the appropriate image.
812 #This "for" loop might be integrated with the previous one
813 #In case this integration is made, the VNFCDict might become a VNFClist.
814 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
815 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
817 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
818 image_dict
['universal_name']=vnfc
.get('image name')
819 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
820 image_dict
['location']=vnfc
.get('VNFC image')
821 #image_dict['new_location']=vnfc.get('image location')
822 image_dict
['checksum']=vnfc
.get('image checksum')
823 image_metadata_dict
= vnfc
.get('image metadata', None)
824 image_metadata_str
= None
825 if image_metadata_dict
is not None:
826 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
827 image_dict
['metadata']=image_metadata_str
828 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
829 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
830 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
831 VNFCDict
[vnfc
['name']]["image_id"] = image_id
832 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
833 if vnfc
.get("boot-data"):
834 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
837 # Step 7. Storing the VNF descriptor in the repository
838 if "descriptor" not in vnf_descriptor
["vnf"]:
839 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
841 # Step 8. Adding the VNF to the NFVO DB
842 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
844 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
845 _
, message
= rollback(mydb
, vims
, rollback_list
)
846 if isinstance(e
, db_base_Exception
):
847 error_text
= "Exception at database"
848 elif isinstance(e
, KeyError):
849 error_text
= "KeyError exception "
850 e
.http_code
= HTTP_Internal_Server_Error
852 error_text
= "Exception at VIM"
853 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
854 #logger.error("start_scenario %s", error_text)
855 raise NfvoException(error_text
, e
.http_code
)
858 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
861 # Step 1. Check the VNF descriptor
862 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
863 # Step 2. Check tenant exist
865 if tenant_id
!= "any":
866 check_tenant(mydb
, tenant_id
)
867 if "tenant_id" in vnf_descriptor
["vnf"]:
868 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
869 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
872 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
873 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
874 if global_config
["auto_push_VNF_to_VIMs"]:
875 vims
= get_vim(mydb
, tenant_id
)
877 # Step 4. Review the descriptor and add missing fields
878 #print vnf_descriptor
879 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
880 vnf_name
= vnf_descriptor
['vnf']['name']
881 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
882 if "physical" in vnf_descriptor
['vnf']:
883 del vnf_descriptor
['vnf']['physical']
884 #print vnf_descriptor
886 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
887 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
888 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
890 #For each VNFC, we add it to the VNFCDict and we create a flavor.
891 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
892 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
894 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
895 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
897 VNFCitem
["name"] = vnfc
['name']
898 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
900 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
903 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
904 myflavorDict
["description"] = VNFCitem
["description"]
905 myflavorDict
["ram"] = vnfc
.get("ram", 0)
906 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
907 myflavorDict
["disk"] = vnfc
.get("disk", 1)
908 myflavorDict
["extended"] = {}
910 devices
= vnfc
.get("devices")
912 myflavorDict
["extended"]["devices"] = devices
915 # 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
916 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
918 # Previous code has been commented
919 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
920 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
921 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
922 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
924 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
926 # print "Error creating flavor: unknown processor model. Rollback successful."
927 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
929 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
930 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
932 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
933 myflavorDict
['extended']['numas'] = vnfc
['numas']
937 # Step 6.2 New flavors are created in the VIM
938 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
940 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
941 VNFCitem
["flavor_id"] = flavor_id
942 VNFCDict
[vnfc
['name']] = VNFCitem
944 logger
.debug("Creating new images in the VIM for each VNFC")
945 # Step 6.3 New images are created in the VIM
946 #For each VNFC, we must create the appropriate image.
947 #This "for" loop might be integrated with the previous one
948 #In case this integration is made, the VNFCDict might become a VNFClist.
949 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
950 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
952 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
953 image_dict
['universal_name']=vnfc
.get('image name')
954 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
955 image_dict
['location']=vnfc
.get('VNFC image')
956 #image_dict['new_location']=vnfc.get('image location')
957 image_dict
['checksum']=vnfc
.get('image checksum')
958 image_metadata_dict
= vnfc
.get('image metadata', None)
959 image_metadata_str
= None
960 if image_metadata_dict
is not None:
961 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
962 image_dict
['metadata']=image_metadata_str
963 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
964 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
965 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
966 VNFCDict
[vnfc
['name']]["image_id"] = image_id
967 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
968 if vnfc
.get("boot-data"):
969 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
971 # Step 7. Storing the VNF descriptor in the repository
972 if "descriptor" not in vnf_descriptor
["vnf"]:
973 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
975 # Step 8. Adding the VNF to the NFVO DB
976 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
978 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
979 _
, message
= rollback(mydb
, vims
, rollback_list
)
980 if isinstance(e
, db_base_Exception
):
981 error_text
= "Exception at database"
982 elif isinstance(e
, KeyError):
983 error_text
= "KeyError exception "
984 e
.http_code
= HTTP_Internal_Server_Error
986 error_text
= "Exception at VIM"
987 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
988 #logger.error("start_scenario %s", error_text)
989 raise NfvoException(error_text
, e
.http_code
)
992 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
993 #check valid tenant_id
994 check_tenant(mydb
, tenant_id
)
997 if tenant_id
!= "any":
998 where_or
["tenant_id"] = tenant_id
999 where_or
["public"] = True
1000 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1003 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
1004 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
1005 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1006 data
={'vnf' : filtered_content
}
1008 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1009 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description', 'boot_data'),
1010 WHERE
={'vnfs.uuid': vnf_id
} )
1012 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1013 # change boot_data into boot-data
1015 if vm
.get("boot_data"):
1016 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1019 data
['vnf']['VNFC'] = content
1020 #TODO: GET all the information from a VNFC and include it in the output.
1023 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1024 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1025 WHERE
={'vnfs.uuid': vnf_id
} )
1026 data
['vnf']['nets'] = content
1028 #GET ip-profile for each net
1029 for net
in data
['vnf']['nets']:
1030 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1031 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1032 WHERE
={'net_id': net
["uuid"]} )
1033 if len(ipprofiles
)==1:
1034 net
["ip_profile"] = ipprofiles
[0]
1035 elif len(ipprofiles
)>1:
1036 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
1039 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1041 #GET External Interfaces
1042 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1043 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1044 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1045 WHERE
={'vnfs.uuid': vnf_id
},
1046 WHERE_NOT
={'interfaces.external_name': None} )
1048 data
['vnf']['external-connections'] = content
1053 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1054 # Check tenant exist
1055 if tenant_id
!= "any":
1056 check_tenant(mydb
, tenant_id
)
1057 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1058 vims
= get_vim(mydb
, tenant_id
)
1062 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1064 if tenant_id
!= "any":
1065 where_or
["tenant_id"] = tenant_id
1066 where_or
["public"] = True
1067 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1068 vnf_id
= vnf
["uuid"]
1070 # "Getting the list of flavors and tenants of the VNF"
1071 flavorList
= get_flavorlist(mydb
, vnf_id
)
1072 if len(flavorList
)==0:
1073 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1075 imageList
= get_imagelist(mydb
, vnf_id
)
1076 if len(imageList
)==0:
1077 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1079 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1081 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1084 for flavor
in flavorList
:
1085 #check if flavor is used by other vnf
1087 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1089 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1091 #flavor not used, must be deleted
1093 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
1094 for flavor_vim
in c
:
1095 if flavor_vim
["datacenter_id"] not in vims
:
1097 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
1099 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
1101 myvim
.delete_flavor(flavor_vim
["vim_id"])
1102 except vimconn
.vimconnNotFoundException
as e
:
1103 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
1104 except vimconn
.vimconnException
as e
:
1105 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1106 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1107 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
1108 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1109 mydb
.delete_row_by_id('flavors', flavor
)
1110 except db_base_Exception
as e
:
1111 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1112 undeletedItems
.append("flavor %s" % flavor
)
1115 for image
in imageList
:
1117 #check if image is used by other vnf
1118 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1120 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1122 #image not used, must be deleted
1124 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1126 if image_vim
["datacenter_id"] not in vims
:
1128 if image_vim
['created']=='false': #skip this image because not created by openmano
1130 myvim
=vims
[ image_vim
["datacenter_id"] ]
1132 myvim
.delete_image(image_vim
["vim_id"])
1133 except vimconn
.vimconnNotFoundException
as e
:
1134 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1135 except vimconn
.vimconnException
as e
:
1136 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1137 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1138 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1139 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1140 mydb
.delete_row_by_id('images', image
)
1141 except db_base_Exception
as e
:
1142 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1143 undeletedItems
.append("image %s" % image
)
1145 return vnf_id
+ " " + vnf
["name"]
1147 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1150 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1151 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1155 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1156 myvim
= vims
.values()[0]
1157 result
,servers
= myvim
.get_hosts_info()
1159 return result
, servers
1160 topology
= {'name':myvim
['name'] , 'servers': servers
}
1161 return result
, topology
1164 def get_hosts(mydb
, nfvo_tenant_id
):
1165 vims
= get_vim(mydb
, nfvo_tenant_id
)
1167 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1169 #print "nfvo.datacenter_action() error. Several datacenters found"
1170 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1171 myvim
= vims
.values()[0]
1173 hosts
= myvim
.get_hosts()
1174 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1176 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1178 server
={'name':host
['name'], 'vms':[]}
1179 for vm
in host
['instances']:
1180 #get internal name and model
1182 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1183 WHERE
={'vim_vm_id':vm
['id']} )
1185 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1187 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1189 except db_base_Exception
as e
:
1190 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1191 datacenter
['Datacenters'][0]['servers'].append(server
)
1192 #return -400, "en construccion"
1194 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1196 except vimconn
.vimconnException
as e
:
1197 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1200 def new_scenario(mydb
, tenant_id
, topo
):
1202 # result, vims = get_vim(mydb, tenant_id)
1204 # return result, vims
1206 if tenant_id
!= "any":
1207 check_tenant(mydb
, tenant_id
)
1208 if "tenant_id" in topo
:
1209 if topo
["tenant_id"] != tenant_id
:
1210 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1215 #1.1: get VNFs and external_networks (other_nets).
1217 other_nets
={} #external_networks, bridge_networks and data_networkds
1218 nodes
= topo
['topology']['nodes']
1219 for k
in nodes
.keys():
1220 if nodes
[k
]['type'] == 'VNF':
1222 vnfs
[k
]['ifaces'] = {}
1223 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1224 other_nets
[k
] = nodes
[k
]
1225 other_nets
[k
]['external']=True
1226 elif nodes
[k
]['type'] == 'network':
1227 other_nets
[k
] = nodes
[k
]
1228 other_nets
[k
]['external']=False
1231 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1232 for name
,vnf
in vnfs
.items():
1234 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1236 error_pos
= "'topology':'nodes':'" + name
+ "'"
1238 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1239 where
['uuid'] = vnf
['vnf_id']
1240 if 'VNF model' in vnf
:
1241 error_text
+= " 'VNF model' " + vnf
['VNF model']
1242 where
['name'] = vnf
['VNF model']
1244 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1246 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1252 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1254 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1255 vnf
['uuid']=vnf_db
[0]['uuid']
1256 vnf
['description']=vnf_db
[0]['description']
1257 #get external interfaces
1258 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1259 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1260 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1261 for ext_iface
in ext_ifaces
:
1262 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1264 #1.4 get list of connections
1265 conections
= topo
['topology']['connections']
1266 conections_list
= []
1267 conections_list_name
= []
1268 for k
in conections
.keys():
1269 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1270 ifaces_list
= conections
[k
]['nodes'].items()
1271 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1273 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1274 for k2
in conection_pair_list
:
1277 con_type
= conections
[k
].get("type", "link")
1278 if con_type
!= "link":
1280 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1281 other_nets
[k
] = {'external': False}
1282 if conections
[k
].get("graph"):
1283 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1284 ifaces_list
.append( (k
, None) )
1287 if con_type
== "external_network":
1288 other_nets
[k
]['external'] = True
1289 if conections
[k
].get("model"):
1290 other_nets
[k
]["model"] = conections
[k
]["model"]
1292 other_nets
[k
]["model"] = k
1293 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1294 other_nets
[k
]["model"] = con_type
1296 conections_list_name
.append(k
)
1297 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)
1298 #print set(ifaces_list)
1299 #check valid VNF and iface names
1300 for iface
in ifaces_list
:
1301 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1302 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1303 str(k
), iface
[0]), HTTP_Not_Found
)
1304 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1305 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1306 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1308 #1.5 unify connections from the pair list to a consolidated list
1310 while index
< len(conections_list
):
1312 while index2
< len(conections_list
):
1313 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1314 conections_list
[index
] |
= conections_list
[index2
]
1315 del conections_list
[index2
]
1316 del conections_list_name
[index2
]
1319 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1321 #for k in conections_list:
1326 #1.6 Delete non external nets
1327 # for k in other_nets.keys():
1328 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1329 # for con in conections_list:
1331 # for index in range(0,len(con)):
1332 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1333 # for index in delete_indexes:
1336 #1.7: Check external_ports are present at database table datacenter_nets
1337 for k
,net
in other_nets
.items():
1338 error_pos
= "'topology':'nodes':'" + k
+ "'"
1339 if net
['external']==False:
1340 if 'name' not in net
:
1342 if 'model' not in net
:
1343 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1344 if net
['model']=='bridge_net':
1345 net
['type']='bridge';
1346 elif net
['model']=='dataplane_net':
1349 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1351 #IF we do not want to check that external network exist at datacenter
1356 # if 'net_id' in net:
1357 # error_text += " 'net_id' " + net['net_id']
1358 # WHERE_['uuid'] = net['net_id']
1359 # if 'model' in net:
1360 # error_text += " 'model' " + net['model']
1361 # WHERE_['name'] = net['model']
1362 # if len(WHERE_) == 0:
1363 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1364 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1365 # FROM='datacenter_nets', WHERE=WHERE_ )
1367 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1369 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1370 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1372 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1373 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1374 # other_nets[k].update(net_db[0])
1377 net_nb
=0 #Number of nets
1378 for con
in conections_list
:
1379 #check if this is connected to a external net
1383 for index
in range(0,len(con
)):
1384 #check if this is connected to a external net
1385 for net_key
in other_nets
.keys():
1386 if con
[index
][0]==net_key
:
1387 if other_net_index
>=0:
1388 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1389 #print "nfvo.new_scenario " + error_text
1390 raise NfvoException(error_text
, HTTP_Bad_Request
)
1392 other_net_index
= index
1393 net_target
= net_key
1395 #print "other_net_index", other_net_index
1397 if other_net_index
>=0:
1398 del con
[other_net_index
]
1399 #IF we do not want to check that external network exist at datacenter
1400 if other_nets
[net_target
]['external'] :
1401 if "name" not in other_nets
[net_target
]:
1402 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1403 if other_nets
[net_target
]["type"] == "external_network":
1404 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1405 other_nets
[net_target
]["type"] = "data"
1407 other_nets
[net_target
]["type"] = "bridge"
1409 # if other_nets[net_target]['external'] :
1410 # 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
1411 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1412 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1413 # print "nfvo.new_scenario " + error_text
1414 # return -HTTP_Bad_Request, error_text
1417 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1420 net_type_bridge
=False
1422 net_target
= "__-__net"+str(net_nb
)
1423 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1424 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1427 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1428 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1429 if iface_type
=='mgmt' or iface_type
=='bridge':
1430 net_type_bridge
= True
1432 net_type_data
= True
1433 if net_type_bridge
and net_type_data
:
1434 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1435 #print "nfvo.new_scenario " + error_text
1436 raise NfvoException(error_text
, HTTP_Bad_Request
)
1437 elif net_type_bridge
:
1440 type_
='data' if len(con
)>2 else 'ptp'
1441 net_list
[net_target
]['type'] = type_
1444 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1445 #print "nfvo.new_scenario " + error_text
1447 raise NfvoException(error_text
, HTTP_Bad_Request
)
1449 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1450 #1.8.1 obtain management net
1451 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1452 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1453 #1.8.2 check all interfaces from all vnfs
1455 add_mgmt_net
= False
1456 for vnf
in vnfs
.values():
1457 for iface
in vnf
['ifaces'].values():
1458 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1459 #iface not connected
1460 iface
['net_key'] = 'mgmt'
1462 if add_mgmt_net
and 'mgmt' not in net_list
:
1463 net_list
['mgmt']=mgmt_net
[0]
1464 net_list
['mgmt']['external']=True
1465 net_list
['mgmt']['graph']={'visible':False}
1467 net_list
.update(other_nets
)
1469 #print 'net_list', net_list
1474 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1475 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1476 'tenant_id':tenant_id
, 'name':topo
['name'],
1477 'description':topo
.get('description',topo
['name']),
1478 'public': topo
.get('public', False)
1484 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
1485 """ This creates a new scenario for version 0.2 and 0.3"""
1486 scenario
= scenario_dict
["scenario"]
1487 if tenant_id
!= "any":
1488 check_tenant(mydb
, tenant_id
)
1489 if "tenant_id" in scenario
:
1490 if scenario
["tenant_id"] != tenant_id
:
1491 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1492 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1493 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1497 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
1498 for name
,vnf
in scenario
["vnfs"].iteritems():
1500 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1502 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1504 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1505 where
['uuid'] = vnf
['vnf_id']
1506 if 'vnf_name' in vnf
:
1507 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1508 where
['name'] = vnf
['vnf_name']
1510 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1511 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
1516 if len(vnf_db
) == 0:
1517 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1518 elif len(vnf_db
) > 1:
1519 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1520 vnf
['uuid'] = vnf_db
[0]['uuid']
1521 vnf
['description'] = vnf_db
[0]['description']
1523 # get external interfaces
1524 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
1525 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1526 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name': None} )
1527 for ext_iface
in ext_ifaces
:
1528 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
1529 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1531 # 2: Insert net_key and ip_address at every vnf interface
1532 for net_name
, net
in scenario
["networks"].items():
1533 net_type_bridge
= False
1534 net_type_data
= False
1535 for iface_dict
in net
["interfaces"]:
1536 if version
== "0.2":
1537 temp_dict
= iface_dict
1539 elif version
== "0.3":
1540 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
1541 ip_address
= iface_dict
.get('ip_address', None)
1542 for vnf
, iface
in temp_dict
.items():
1543 if vnf
not in scenario
["vnfs"]:
1544 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
1546 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1547 raise NfvoException(error_text
, HTTP_Not_Found
)
1548 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1549 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
1550 .format(net_name
, iface
)
1551 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1552 raise NfvoException(error_text
, HTTP_Bad_Request
)
1553 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1554 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
1555 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1556 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1557 raise NfvoException(error_text
, HTTP_Bad_Request
)
1558 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1559 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
1560 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1561 if iface_type
== 'mgmt' or iface_type
== 'bridge':
1562 net_type_bridge
= True
1564 net_type_data
= True
1566 if net_type_bridge
and net_type_data
:
1567 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
1569 # logger.debug("nfvo.new_scenario " + error_text)
1570 raise NfvoException(error_text
, HTTP_Bad_Request
)
1571 elif net_type_bridge
:
1574 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
1576 if net
.get("implementation"): # for v0.3
1577 if type_
== "bridge" and net
["implementation"] == "underlay":
1578 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
1579 "'network':'{}'".format(net_name
)
1580 # logger.debug(error_text)
1581 raise NfvoException(error_text
, HTTP_Bad_Request
)
1582 elif type_
!= "bridge" and net
["implementation"] == "overlay":
1583 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
1584 "'network':'{}'".format(net_name
)
1585 # logger.debug(error_text)
1586 raise NfvoException(error_text
, HTTP_Bad_Request
)
1587 net
.pop("implementation")
1588 if "type" in net
and version
== "0.3": # for v0.3
1589 if type_
== "data" and net
["type"] == "e-line":
1590 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
1591 "'e-line' at 'network':'{}'".format(net_name
)
1592 # logger.debug(error_text)
1593 raise NfvoException(error_text
, HTTP_Bad_Request
)
1594 elif type_
== "ptp" and net
["type"] == "e-lan":
1598 net
['name'] = net_name
1599 net
['external'] = net
.get('external', False)
1601 # 3: insert at database
1602 scenario
["nets"] = scenario
["networks"]
1603 scenario
['tenant_id'] = tenant_id
1604 scenario_id
= mydb
.new_scenario(scenario
)
1608 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1609 data
["uuid"] = scenario_id
1610 data
["tenant_id"] = tenant_id
1611 c
= mydb
.edit_scenario( data
)
1615 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1616 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1617 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
1618 vims
= {datacenter_id
: myvim
}
1619 myvim_tenant
= myvim
['tenant_id']
1620 datacenter_name
= myvim
['name']
1624 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1625 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1626 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
1627 scenarioDict
['datacenter_id'] = datacenter_id
1628 #print '================scenarioDict======================='
1629 #print json.dumps(scenarioDict, indent=4)
1630 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1632 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1633 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1635 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1636 auxNetDict
['scenario'] = {}
1638 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1639 for sce_net
in scenarioDict
['nets']:
1640 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1642 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1643 myNetName
= myNetName
[0:255] #limit length
1644 myNetType
= sce_net
['type']
1646 myNetDict
["name"] = myNetName
1647 myNetDict
["type"] = myNetType
1648 myNetDict
["tenant_id"] = myvim_tenant
1649 myNetIPProfile
= sce_net
.get('ip_profile', None)
1651 #We should use the dictionary as input parameter for new_network
1653 if not sce_net
["external"]:
1654 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1655 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1656 sce_net
['vim_id'] = network_id
1657 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1658 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1659 sce_net
["created"] = True
1661 if sce_net
['vim_id'] == None:
1662 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1663 _
, message
= rollback(mydb
, vims
, rollbackList
)
1664 logger
.error("nfvo.start_scenario: %s", error_text
)
1665 raise NfvoException(error_text
, HTTP_Bad_Request
)
1666 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1667 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1669 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1670 #For each vnf net, we create it and we add it to instanceNetlist.
1672 for sce_vnf
in scenarioDict
['vnfs']:
1673 for net
in sce_vnf
['nets']:
1674 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1676 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1677 myNetName
= myNetName
[0:255] #limit length
1678 myNetType
= net
['type']
1680 myNetDict
["name"] = myNetName
1681 myNetDict
["type"] = myNetType
1682 myNetDict
["tenant_id"] = myvim_tenant
1683 myNetIPProfile
= net
.get('ip_profile', None)
1686 #We should use the dictionary as input parameter for new_network
1687 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1688 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1689 net
['vim_id'] = network_id
1690 if sce_vnf
['uuid'] not in auxNetDict
:
1691 auxNetDict
[sce_vnf
['uuid']] = {}
1692 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1693 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1694 net
["created"] = True
1696 #print "auxNetDict:"
1697 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1699 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1700 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1702 for sce_vnf
in scenarioDict
['vnfs']:
1703 nfv_availability_zones
= []
1704 for vm
in sce_vnf
['vms']:
1705 vm_av
= vm
.get('availability_zone')
1706 if vm_av
and vm_av
not in nfv_availability_zones
:
1707 nfv_availability_zones
.append(vm_av
)
1708 for vm
in sce_vnf
['vms']:
1711 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1712 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
1713 #myVMDict['description'] = vm['description']
1714 myVMDict
['description'] = myVMDict
['name'][0:99]
1716 myVMDict
['start'] = "no"
1717 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1718 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1720 #create image at vim in case it not exist
1721 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1722 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1723 vm
['vim_image_id'] = image_id
1725 #create flavor at vim in case it not exist
1726 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1727 if flavor_dict
['extended']!=None:
1728 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1729 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1730 vm
['vim_flavor_id'] = flavor_id
1733 myVMDict
['imageRef'] = vm
['vim_image_id']
1734 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1735 myVMDict
['networks'] = []
1736 for iface
in vm
['interfaces']:
1738 if iface
['type']=="data":
1739 netDict
['type'] = iface
['model']
1740 elif "model" in iface
and iface
["model"]!=None:
1741 netDict
['model']=iface
['model']
1742 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1743 #discover type of interface looking at flavor
1744 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1745 for flavor_iface
in numa
.get('interfaces',[]):
1746 if flavor_iface
.get('name') == iface
['internal_name']:
1747 if flavor_iface
['dedicated'] == 'yes':
1748 netDict
['type']="PF" #passthrough
1749 elif flavor_iface
['dedicated'] == 'no':
1750 netDict
['type']="VF" #siov
1751 elif flavor_iface
['dedicated'] == 'yes:sriov':
1752 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1753 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1755 netDict
["use"]=iface
['type']
1756 if netDict
["use"]=="data" and not netDict
.get("type"):
1757 #print "netDict", netDict
1758 #print "iface", iface
1759 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'])
1760 if flavor_dict
.get('extended')==None:
1761 raise NfvoException(e_text
+ "After database migration some information is not available. \
1762 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1764 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1765 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1766 netDict
["type"]="virtual"
1767 if "vpci" in iface
and iface
["vpci"] is not None:
1768 netDict
['vpci'] = iface
['vpci']
1769 if "mac" in iface
and iface
["mac"] is not None:
1770 netDict
['mac_address'] = iface
['mac']
1771 if "port-security" in iface
and iface
["port-security"] is not None:
1772 netDict
['port_security'] = iface
['port-security']
1773 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
1774 netDict
['floating_ip'] = iface
['floating-ip']
1775 netDict
['name'] = iface
['internal_name']
1776 if iface
['net_id'] is None:
1777 for vnf_iface
in sce_vnf
["interfaces"]:
1780 if vnf_iface
['interface_id']==iface
['uuid']:
1781 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1784 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1785 #skip bridge ifaces not connected to any net
1786 #if 'net_id' not in netDict or netDict['net_id']==None:
1788 myVMDict
['networks'].append(netDict
)
1789 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1790 #print myVMDict['name']
1791 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1792 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1793 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1795 if 'availability_zone' in myVMDict
:
1796 counter_availability_zone
= nfv_availability_zones
.index(myVMDict
['availability_zone'])
1798 counter_availability_zone
= None
1800 vm_id
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
1801 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
1802 availavility_zone_index
=counter_availability_zone
,
1803 nfv_availability_zones
=nfv_availability_zones
)
1804 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1805 vm
['vim_id'] = vm_id
1806 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1807 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1808 for net
in myVMDict
['networks']:
1810 for iface
in vm
['interfaces']:
1811 if net
["name"]==iface
["internal_name"]:
1812 iface
["vim_id"]=net
["vim_id"]
1815 logger
.debug("start scenario Deployment done")
1816 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1817 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1818 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1819 return mydb
.get_instance_scenario(instance_id
)
1821 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1822 _
, message
= rollback(mydb
, vims
, rollbackList
)
1823 if isinstance(e
, db_base_Exception
):
1824 error_text
= "Exception at database"
1826 error_text
= "Exception at VIM"
1827 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1828 #logger.error("start_scenario %s", error_text)
1829 raise NfvoException(error_text
, e
.http_code
)
1832 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
1833 ''' join the cloud config information into cloud_config_preserve.
1834 In case of conflict cloud_config_preserve preserves
1837 if not cloud_config_preserve
and not cloud_config
:
1840 new_cloud_config
= {"key-pairs":[], "users":[]}
1842 if cloud_config_preserve
:
1843 for key
in cloud_config_preserve
.get("key-pairs", () ):
1844 if key
not in new_cloud_config
["key-pairs"]:
1845 new_cloud_config
["key-pairs"].append(key
)
1847 for key
in cloud_config
.get("key-pairs", () ):
1848 if key
not in new_cloud_config
["key-pairs"]:
1849 new_cloud_config
["key-pairs"].append(key
)
1850 if not new_cloud_config
["key-pairs"]:
1851 del new_cloud_config
["key-pairs"]
1855 new_cloud_config
["users"] += cloud_config
.get("users", () )
1856 if cloud_config_preserve
:
1857 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
1858 index_to_delete
= []
1859 users
= new_cloud_config
.get("users", [])
1860 for index0
in range(0,len(users
)):
1861 if index0
in index_to_delete
:
1863 for index1
in range(index0
+1,len(users
)):
1864 if index1
in index_to_delete
:
1866 if users
[index0
]["name"] == users
[index1
]["name"]:
1867 index_to_delete
.append(index1
)
1868 for key
in users
[index1
].get("key-pairs",()):
1869 if "key-pairs" not in users
[index0
]:
1870 users
[index0
]["key-pairs"] = [key
]
1871 elif key
not in users
[index0
]["key-pairs"]:
1872 users
[index0
]["key-pairs"].append(key
)
1873 index_to_delete
.sort(reverse
=True)
1874 for index
in index_to_delete
:
1876 if not new_cloud_config
["users"]:
1877 del new_cloud_config
["users"]
1880 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
1881 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
1882 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
1883 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
1886 if cloud_config
and cloud_config
.get("user-data") != None:
1887 new_cloud_config
["user-data"] = cloud_config
["user-data"]
1888 if cloud_config_preserve
and cloud_config_preserve
.get("user-data") != None:
1889 new_cloud_config
["user-data"] = cloud_config_preserve
["user-data"]
1892 new_cloud_config
["config-files"] = []
1893 if cloud_config
and cloud_config
.get("config-files") != None:
1894 new_cloud_config
["config-files"] += cloud_config
["config-files"]
1895 if cloud_config_preserve
:
1896 for file in cloud_config_preserve
.get("config-files", ()):
1897 for index
in range(0, len(new_cloud_config
["config-files"])):
1898 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
1899 new_cloud_config
["config-files"][index
] = file
1902 new_cloud_config
["config-files"].append(file)
1903 if not new_cloud_config
["config-files"]:
1904 del new_cloud_config
["config-files"]
1905 return new_cloud_config
1908 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
1909 datacenter_id
= None
1910 datacenter_name
= None
1913 if datacenter_tenant_id
:
1914 thread_id
= datacenter_tenant_id
1915 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
1917 where_
={"td.nfvo_tenant_id": tenant_id
}
1918 if datacenter_id_name
:
1919 if utils
.check_valid_uuid(datacenter_id_name
):
1920 datacenter_id
= datacenter_id_name
1921 where_
["dt.datacenter_id"] = datacenter_id
1923 datacenter_name
= datacenter_id_name
1924 where_
["d.name"] = datacenter_name
1925 if datacenter_tenant_id
:
1926 where_
["dt.uuid"] = datacenter_tenant_id
1927 datacenters
= mydb
.get_rows(
1928 SELECT
=("dt.uuid as datacenter_tenant_id",),
1929 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
1930 "join datacenters as d on d.uuid=dt.datacenter_id",
1932 if len(datacenters
) > 1:
1933 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1935 thread_id
= datacenters
[0]["datacenter_tenant_id"]
1936 thread
= vim_threads
["running"].get(thread_id
)
1938 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1939 return thread_id
, thread
1940 except db_base_Exception
as e
:
1941 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
1944 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1945 datacenter_id
= None
1946 datacenter_name
= None
1947 if datacenter_id_name
:
1948 if utils
.check_valid_uuid(datacenter_id_name
):
1949 datacenter_id
= datacenter_id_name
1951 datacenter_name
= datacenter_id_name
1952 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1954 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1956 #print "nfvo.datacenter_action() error. Several datacenters found"
1957 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1958 return vims
.keys()[0], vims
.values()[0]
1962 '''Takes dict d and updates it with the values in dict u.'''
1963 '''It merges all depth levels'''
1964 for k
, v
in u
.iteritems():
1965 if isinstance(v
, collections
.Mapping
):
1966 r
= update(d
.get(k
, {}), v
)
1973 def create_instance(mydb
, tenant_id
, instance_dict
):
1974 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1975 # logger.debug("Creating instance...")
1976 scenario
= instance_dict
["scenario"]
1978 #find main datacenter
1980 myvim_threads_id
= {}
1983 datacenter
= instance_dict
.get("datacenter")
1984 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1985 myvims
[default_datacenter_id
] = vim
1986 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
1987 tasks_to_launch
[myvim_threads_id
[default_datacenter_id
]] = []
1988 #myvim_tenant = myvim['tenant_id']
1989 # default_datacenter_name = vim['name']
1992 #print "Checking that the scenario exists and getting the scenario dictionary"
1993 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1995 #logger.debug(">>>>>>> Dictionaries before merging")
1996 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1997 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1999 scenarioDict
['datacenter_id'] = default_datacenter_id
2001 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2002 auxNetDict
['scenario'] = {}
2004 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
2005 instance_name
= instance_dict
["name"]
2006 instance_description
= instance_dict
.get("description")
2008 # 0 check correct parameters
2009 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2011 for scenario_net
in scenarioDict
['nets']:
2012 if net_name
== scenario_net
["name"]:
2016 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
2017 if "sites" not in net_instance_desc
:
2018 net_instance_desc
["sites"] = [ {} ]
2019 site_without_datacenter_field
= False
2020 for site
in net_instance_desc
["sites"]:
2021 if site
.get("datacenter"):
2022 if site
["datacenter"] not in myvims
:
2023 #Add this datacenter to myvims
2024 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
2026 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
2027 tasks_to_launch
[myvim_threads_id
[d
]] = []
2028 site
["datacenter"] = d
#change name to id
2030 if site_without_datacenter_field
:
2031 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
2032 site_without_datacenter_field
= True
2033 site
["datacenter"] = default_datacenter_id
#change name to id
2035 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
2037 for scenario_vnf
in scenarioDict
['vnfs']:
2038 if vnf_name
== scenario_vnf
['name']:
2042 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
2043 if "datacenter" in vnf_instance_desc
:
2044 # Add this datacenter to myvims
2045 if vnf_instance_desc
["datacenter"] not in myvims
:
2046 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2048 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2049 tasks_to_launch
[myvim_threads_id
[d
]] = []
2050 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2052 #0.1 parse cloud-config parameters
2053 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2055 #0.2 merge instance information into scenario
2056 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2057 #However, this is not possible yet.
2058 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2059 for scenario_net
in scenarioDict
['nets']:
2060 if net_name
== scenario_net
["name"]:
2061 if 'ip-profile' in net_instance_desc
:
2062 # translate from input format to database format
2063 ipprofile_in
= net_instance_desc
['ip-profile']
2065 ipprofile_db
['subnet_address'] = ipprofile_in
.get('subnet-address')
2066 ipprofile_db
['ip_version'] = ipprofile_in
.get('ip-version', 'IPv4')
2067 ipprofile_db
['gateway_address'] = ipprofile_in
.get('gateway-address')
2068 ipprofile_db
['dns_address'] = ipprofile_in
.get('dns-address')
2069 if isinstance(ipprofile_db
['dns_address'], (list, tuple)):
2070 ipprofile_db
['dns_address'] = ";".join(ipprofile_db
['dns_address'])
2071 if 'dhcp' in ipprofile_in
:
2072 ipprofile_db
['dhcp_start_address'] = ipprofile_in
['dhcp'].get('start-address')
2073 ipprofile_db
['dhcp_enabled'] = ipprofile_in
['dhcp'].get('enabled', True)
2074 ipprofile_db
['dhcp_count'] = ipprofile_in
['dhcp'].get('count' )
2075 if 'ip_profile' not in scenario_net
:
2076 scenario_net
['ip_profile'] = ipprofile_db
2078 update(scenario_net
['ip_profile'], ipprofile_db
)
2079 for interface
in net_instance_desc
.get('interfaces', () ):
2080 if 'ip_address' in interface
:
2081 for vnf
in scenarioDict
['vnfs']:
2082 if interface
['vnf'] == vnf
['name']:
2083 for vnf_interface
in vnf
['interfaces']:
2084 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2085 vnf_interface
['ip_address']=interface
['ip_address']
2087 #logger.debug(">>>>>>>> Merged dictionary")
2088 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
2091 # 1. Creating new nets (sce_nets) in the VIM"
2092 for sce_net
in scenarioDict
['nets']:
2093 sce_net
["vim_id_sites"]={}
2094 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
2095 net_name
= descriptor_net
.get("vim-network-name")
2096 auxNetDict
['scenario'][sce_net
['uuid']] = {}
2098 sites
= descriptor_net
.get("sites", [ {} ])
2100 if site
.get("datacenter"):
2101 vim
= myvims
[ site
["datacenter"] ]
2102 datacenter_id
= site
["datacenter"]
2103 myvim_thread_id
= myvim_threads_id
[ site
["datacenter"] ]
2105 vim
= myvims
[ default_datacenter_id
]
2106 datacenter_id
= default_datacenter_id
2107 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2108 net_type
= sce_net
['type']
2109 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
2110 if sce_net
["external"]:
2112 net_name
= sce_net
["name"]
2113 if "netmap-use" in site
or "netmap-create" in site
:
2114 create_network
= False
2115 lookfor_network
= False
2116 if "netmap-use" in site
:
2117 lookfor_network
= True
2118 if utils
.check_valid_uuid(site
["netmap-use"]):
2119 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2120 lookfor_filter
["id"] = site
["netmap-use"]
2122 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2123 lookfor_filter
["name"] = site
["netmap-use"]
2124 if "netmap-create" in site
:
2125 create_network
= True
2126 net_vim_name
= net_name
2127 if site
["netmap-create"]:
2128 net_vim_name
= site
["netmap-create"]
2130 elif sce_net
['vim_id'] != None:
2131 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
2132 create_network
= False
2133 lookfor_network
= True
2134 lookfor_filter
["id"] = sce_net
['vim_id']
2135 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
2136 #look for network at datacenter and return error
2138 #There is not a netmap, look at datacenter for a net with this name and create if not found
2139 create_network
= True
2140 lookfor_network
= True
2141 lookfor_filter
["name"] = sce_net
["name"]
2142 net_vim_name
= sce_net
["name"]
2143 filter_text
= "scenario name '%s'" % sce_net
["name"]
2146 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
2147 net_name
= net_name
[:255] #limit length
2148 net_vim_name
= net_name
2149 create_network
= True
2150 lookfor_network
= False
2153 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
2154 if len(vim_nets
) > 1:
2155 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2156 elif len(vim_nets
) == 0:
2157 if not create_network
:
2158 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2160 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
2161 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
2162 create_network
= False
2164 #if network is not external
2165 task
= new_task("new-net", (net_vim_name
, net_type
, sce_net
.get('ip_profile',None)))
2166 task_id
= task
["id"]
2167 instance_tasks
[task_id
] = task
2168 tasks_to_launch
[myvim_thread_id
].append(task
)
2169 #network_id = vim.new_network(net_vim_name, net_type, sce_net.get('ip_profile',None))
2170 sce_net
["vim_id_sites"][datacenter_id
] = task_id
2171 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = task_id
2172 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':task_id
})
2173 sce_net
["created"] = True
2175 # 2. Creating new nets (vnf internal nets) in the VIM"
2176 # For each vnf net, we create it and we add it to instanceNetlist.
2177 for sce_vnf
in scenarioDict
['vnfs']:
2178 for net
in sce_vnf
['nets']:
2179 if sce_vnf
.get("datacenter"):
2180 vim
= myvims
[ sce_vnf
["datacenter"] ]
2181 datacenter_id
= sce_vnf
["datacenter"]
2182 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"]]
2184 vim
= myvims
[ default_datacenter_id
]
2185 datacenter_id
= default_datacenter_id
2186 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2187 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
2188 net_name
= descriptor_net
.get("name")
2190 net_name
= "%s.%s" %(instance_name
, net
["name"])
2191 net_name
= net_name
[:255] #limit length
2192 net_type
= net
['type']
2193 task
= new_task("new-net", (net_name
, net_type
, net
.get('ip_profile',None)))
2194 task_id
= task
["id"]
2195 instance_tasks
[task_id
] = task
2196 tasks_to_launch
[myvim_thread_id
].append(task
)
2197 # network_id = vim.new_network(net_name, net_type, net.get('ip_profile',None))
2198 net
['vim_id'] = task_id
2199 if sce_vnf
['uuid'] not in auxNetDict
:
2200 auxNetDict
[sce_vnf
['uuid']] = {}
2201 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = task_id
2202 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':task_id
})
2203 net
["created"] = True
2205 #print "auxNetDict:"
2206 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2208 # 3. Creating new vm instances in the VIM
2209 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2211 sce_vnf_list
= sorted(scenarioDict
['vnfs'], key
=lambda k
: k
['name'])
2212 #for sce_vnf in scenarioDict['vnfs']:
2213 for sce_vnf
in sce_vnf_list
:
2214 nfv_availability_zones
= []
2215 for vm
in sce_vnf
['vms']:
2216 vm_av
= vm
.get('availability_zone')
2217 if vm_av
and vm_av
not in nfv_availability_zones
:
2218 nfv_availability_zones
.append(vm_av
)
2220 # check if there is enough availability zones available at vim level.
2221 if myvims
[datacenter_id
].availability_zone
:
2222 vim_availability_zones
= myvims
[datacenter_id
].availability_zone
2223 nfv_availability_zones_num
= len(vim_availability_zones
)
2224 if len(nfv_availability_zones
) > nfv_availability_zones_num
:
2225 raise NfvoException('No enough availablity zones for this deployment', HTTP_Bad_Request
)
2227 if sce_vnf
.get("datacenter"):
2228 vim
= myvims
[ sce_vnf
["datacenter"] ]
2229 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"] ]
2230 datacenter_id
= sce_vnf
["datacenter"]
2232 vim
= myvims
[ default_datacenter_id
]
2233 myvim_thread_id
= myvim_threads_id
[ default_datacenter_id
]
2234 datacenter_id
= default_datacenter_id
2235 sce_vnf
["datacenter_id"] = datacenter_id
2238 for vm
in sce_vnf
['vms']:
2241 myVMDict
['name'] = "{}.{}.{}".format(instance_name
,sce_vnf
['name'],chr(96+i
))
2242 myVMDict
['description'] = myVMDict
['name'][0:99]
2244 # myVMDict['start'] = "no"
2245 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2246 #create image at vim in case it not exist
2247 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2248 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2249 vm
['vim_image_id'] = image_id
2251 #create flavor at vim in case it not exist
2252 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2253 if flavor_dict
['extended']!=None:
2254 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2255 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
2257 #Obtain information for additional disks
2258 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
2259 if not extended_flavor_dict
:
2260 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
2263 #extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
2264 myVMDict
['disks'] = None
2265 extended_info
= extended_flavor_dict
[0]['extended']
2266 if extended_info
!= None:
2267 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
2268 if 'disks' in extended_flavor_dict_yaml
:
2269 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
2271 vm
['vim_flavor_id'] = flavor_id
2272 myVMDict
['imageRef'] = vm
['vim_image_id']
2273 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2274 myVMDict
['availability_zone'] = vm
.get('availability_zone')
2275 myVMDict
['networks'] = []
2277 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
2278 for iface
in vm
['interfaces']:
2280 if iface
['type']=="data":
2281 netDict
['type'] = iface
['model']
2282 elif "model" in iface
and iface
["model"]!=None:
2283 netDict
['model']=iface
['model']
2284 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2285 #discover type of interface looking at flavor
2286 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2287 for flavor_iface
in numa
.get('interfaces',[]):
2288 if flavor_iface
.get('name') == iface
['internal_name']:
2289 if flavor_iface
['dedicated'] == 'yes':
2290 netDict
['type']="PF" #passthrough
2291 elif flavor_iface
['dedicated'] == 'no':
2292 netDict
['type']="VF" #siov
2293 elif flavor_iface
['dedicated'] == 'yes:sriov':
2294 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2295 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2297 netDict
["use"]=iface
['type']
2298 if netDict
["use"]=="data" and not netDict
.get("type"):
2299 #print "netDict", netDict
2300 #print "iface", iface
2301 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'])
2302 if flavor_dict
.get('extended')==None:
2303 raise NfvoException(e_text
+ "After database migration some information is not available. \
2304 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2306 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2307 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2308 netDict
["type"]="virtual"
2309 if "vpci" in iface
and iface
["vpci"] is not None:
2310 netDict
['vpci'] = iface
['vpci']
2311 if "mac" in iface
and iface
["mac"] is not None:
2312 netDict
['mac_address'] = iface
['mac']
2313 if "port-security" in iface
and iface
["port-security"] is not None:
2314 netDict
['port_security'] = iface
['port-security']
2315 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2316 netDict
['floating_ip'] = iface
['floating-ip']
2317 netDict
['name'] = iface
['internal_name']
2318 if iface
['net_id'] is None:
2319 for vnf_iface
in sce_vnf
["interfaces"]:
2322 if vnf_iface
['interface_id']==iface
['uuid']:
2323 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
2326 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2327 if netDict
.get('net_id') and is_task_id(netDict
['net_id']):
2328 task_depends
[netDict
['net_id']] = instance_tasks
[netDict
['net_id']]
2329 #skip bridge ifaces not connected to any net
2330 #if 'net_id' not in netDict or netDict['net_id']==None:
2332 myVMDict
['networks'].append(netDict
)
2333 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2334 #print myVMDict['name']
2335 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2336 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2337 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2338 if vm
.get("boot_data"):
2339 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
2341 cloud_config_vm
= cloud_config
2343 if 'availability_zone' in myVMDict
and myVMDict
.get('availability_zone'):
2344 counter_availability_zone
= nfv_availability_zones
.index(myVMDict
['availability_zone'])
2346 counter_availability_zone
= None
2347 task
= new_task("new-vm", (myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2348 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2349 cloud_config_vm
, myVMDict
['disks'], counter_availability_zone
,
2350 nfv_availability_zones
), depends
=task_depends
)
2351 instance_tasks
[task
["id"]] = task
2352 tasks_to_launch
[myvim_thread_id
].append(task
)
2354 vm
['vim_id'] = vm_id
2355 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2356 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2357 for net
in myVMDict
['networks']:
2359 for iface
in vm
['interfaces']:
2360 if net
["name"]==iface
["internal_name"]:
2361 iface
["vim_id"]=net
["vim_id"]
2363 scenarioDict
["datacenter2tenant"] = myvim_threads_id
2364 logger
.debug("create_instance Deployment done scenarioDict: %s",
2365 yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False) )
2366 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
2367 for myvim_thread_id
,task_list
in tasks_to_launch
.items():
2368 for task
in task_list
:
2369 vim_threads
["running"][myvim_thread_id
].insert_task(task
)
2371 global_instance_tasks
[instance_id
] = instance_tasks
2372 # Update database with those ended instance_tasks
2373 # for task in instance_tasks.values():
2374 # if task["status"] == "ok":
2375 # if task["name"] == "new-vm":
2376 # mydb.update_rows("instance_vms", UPDATE={"vim_vm_id": task["result"]},
2377 # WHERE={"vim_vm_id": task["id"]})
2378 # elif task["name"] == "new-net":
2379 # mydb.update_rows("instance_nets", UPDATE={"vim_net_id": task["result"]},
2380 # WHERE={"vim_net_id": task["id"]})
2381 return mydb
.get_instance_scenario(instance_id
)
2382 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2383 message
= rollback(mydb
, myvims
, rollbackList
)
2384 if isinstance(e
, db_base_Exception
):
2385 error_text
= "database Exception"
2386 elif isinstance(e
, vimconn
.vimconnException
):
2387 error_text
= "VIM Exception"
2389 error_text
= "Exception"
2390 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2391 #logger.error("create_instance: %s", error_text)
2392 raise NfvoException(error_text
, e
.http_code
)
2395 def delete_instance(mydb
, tenant_id
, instance_id
):
2396 #print "Checking that the instance_id exists and getting the instance dictionary"
2397 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2398 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2399 tenant_id
= instanceDict
["tenant_id"]
2400 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2402 #1. Delete from Database
2403 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2412 for sce_vnf
in instanceDict
['vnfs']:
2413 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2414 if datacenter_key
not in myvims
:
2416 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2417 except NfvoException
as e
:
2418 logger
.error(str(e
))
2420 myvim_threads
[datacenter_key
] = myvim_thread
2421 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2422 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2424 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2425 sce_vnf
["datacenter_tenant_id"]))
2426 myvims
[datacenter_key
] = None
2428 myvims
[datacenter_key
] = vims
.values()[0]
2429 myvim
= myvims
[datacenter_key
]
2430 myvim_thread
= myvim_threads
[datacenter_key
]
2431 for vm
in sce_vnf
['vms']:
2433 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2437 if is_task_id(vm
['vim_vm_id']):
2438 task_id
= vm
['vim_vm_id']
2439 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2441 error_msg
+= "\n VM was scheduled for create, but task {} is not found".format(task_id
)
2444 if old_task
["status"] == "enqueued":
2445 old_task
["status"] = "deleted"
2446 elif old_task
["status"] == "error":
2448 elif old_task
["status"] == "processing":
2449 task
= new_task("del-vm", (task_id
, vm
["interfaces"]), depends
={task_id
: old_task
})
2451 task
= new_task("del-vm", (old_task
["result"], vm
["interfaces"]))
2453 task
= new_task("del-vm", (vm
['vim_vm_id'], vm
["interfaces"]) )
2455 myvim_thread
.insert_task(task
)
2456 except vimconn
.vimconnNotFoundException
as e
:
2457 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2458 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2459 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2460 except vimconn
.vimconnException
as e
:
2461 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2462 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2463 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2467 for net
in instanceDict
['nets']:
2468 if not net
['created']:
2469 continue #skip not created nets
2470 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2471 if datacenter_key
not in myvims
:
2473 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2474 except NfvoException
as e
:
2475 logger
.error(str(e
))
2477 myvim_threads
[datacenter_key
] = myvim_thread
2478 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2479 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2481 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2482 myvims
[datacenter_key
] = None
2484 myvims
[datacenter_key
] = vims
.values()[0]
2485 myvim
= myvims
[datacenter_key
]
2486 myvim_thread
= myvim_threads
[datacenter_key
]
2489 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2493 if is_task_id(net
['vim_net_id']):
2494 task_id
= net
['vim_net_id']
2495 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2497 error_msg
+= "\n NET was scheduled for create, but task {} is not found".format(task_id
)
2500 if old_task
["status"] == "enqueued":
2501 old_task
["status"] = "deleted"
2502 elif old_task
["status"] == "error":
2504 elif old_task
["status"] == "processing":
2505 task
= new_task("del-net", task_id
, depends
={task_id
: old_task
})
2507 task
= new_task("del-net", old_task
["result"])
2509 task
= new_task("del-net", (net
['vim_net_id'], net
['sdn_net_id']))
2511 myvim_thread
.insert_task(task
)
2512 except vimconn
.vimconnNotFoundException
as e
:
2513 error_msg
+= "\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2514 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2515 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2516 except vimconn
.vimconnException
as e
:
2517 error_msg
+= "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'],
2518 net
["datacenter_id"],
2519 e
.http_code
, str(e
))
2520 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2521 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2522 if len(error_msg
) > 0:
2523 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2525 return 'instance ' + message
+ ' deleted'
2528 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2529 '''Refreshes a scenario instance. It modifies instanceDict'''
2531 - 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
2534 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2535 # #print "nfvo.refresh_instance begins"
2536 # #print json.dumps(instanceDict, indent=4)
2538 # #print "Getting the VIM URL and the VIM tenant_id"
2541 # # 1. Getting VIM vm and net list
2542 # vms_updated = [] #List of VM instance uuids in openmano that were updated
2545 # for sce_vnf in instanceDict['vnfs']:
2546 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
2547 # if datacenter_key not in vm_list:
2548 # vm_list[datacenter_key] = []
2549 # if datacenter_key not in myvims:
2550 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
2551 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
2552 # if len(vims) == 0:
2553 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
2554 # myvims[datacenter_key] = None
2556 # myvims[datacenter_key] = vims.values()[0]
2557 # for vm in sce_vnf['vms']:
2558 # vm_list[datacenter_key].append(vm['vim_vm_id'])
2559 # vms_notupdated.append(vm["uuid"])
2561 # nets_updated = [] #List of VM instance uuids in openmano that were updated
2562 # nets_notupdated=[]
2564 # for net in instanceDict['nets']:
2565 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
2566 # if datacenter_key not in net_list:
2567 # net_list[datacenter_key] = []
2568 # if datacenter_key not in myvims:
2569 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
2570 # datacenter_tenant_id=net["datacenter_tenant_id"])
2571 # if len(vims) == 0:
2572 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
2573 # myvims[datacenter_key] = None
2575 # myvims[datacenter_key] = vims.values()[0]
2577 # net_list[datacenter_key].append(net['vim_net_id'])
2578 # nets_notupdated.append(net["uuid"])
2580 # # 1. Getting the status of all VMs
2582 # for datacenter_key in myvims:
2583 # if not vm_list.get(datacenter_key):
2587 # if not myvims[datacenter_key]:
2588 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2591 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
2593 # except vimconn.vimconnException as e:
2594 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2595 # failed_message = str(e)
2597 # for vm in vm_list[datacenter_key]:
2598 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2600 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2601 # for sce_vnf in instanceDict['vnfs']:
2602 # for vm in sce_vnf['vms']:
2603 # vm_id = vm['vim_vm_id']
2604 # interfaces = vm_dict[vm_id].pop('interfaces', [])
2605 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2606 # has_mgmt_iface = False
2607 # for iface in vm["interfaces"]:
2608 # if iface["type"]=="mgmt":
2609 # has_mgmt_iface = True
2610 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
2611 # vm_dict[vm_id]['status'] = "ACTIVE"
2612 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
2613 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
2614 # 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'):
2615 # vm['status'] = vm_dict[vm_id]['status']
2616 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
2617 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
2618 # # 2.1. Update in openmano DB the VMs whose status changed
2620 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
2621 # vms_notupdated.remove(vm["uuid"])
2623 # vms_updated.append(vm["uuid"])
2624 # except db_base_Exception as e:
2625 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2626 # # 2.2. Update in openmano DB the interface VMs
2627 # for interface in interfaces:
2628 # #translate from vim_net_id to instance_net_id
2629 # network_id_list=[]
2630 # for net in instanceDict['nets']:
2631 # if net["vim_net_id"] == interface["vim_net_id"]:
2632 # network_id_list.append(net["uuid"])
2633 # if not network_id_list:
2635 # del interface["vim_net_id"]
2637 # for network_id in network_id_list:
2638 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
2639 # except db_base_Exception as e:
2640 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
2642 # # 3. Getting the status of all nets
2644 # for datacenter_key in myvims:
2645 # if not net_list.get(datacenter_key):
2648 # failed_message = ""
2649 # if not myvims[datacenter_key]:
2650 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2653 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
2655 # except vimconn.vimconnException as e:
2656 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2657 # failed_message = str(e)
2659 # for net in net_list[datacenter_key]:
2660 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2662 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2663 # # TODO: update nets inside a vnf
2664 # for net in instanceDict['nets']:
2665 # net_id = net['vim_net_id']
2666 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
2667 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
2668 # 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'):
2669 # net['status'] = net_dict[net_id]['status']
2670 # net['error_msg'] = net_dict[net_id].get('error_msg')
2671 # net['vim_info'] = net_dict[net_id].get('vim_info')
2672 # # 5.1. Update in openmano DB the nets whose status changed
2674 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
2675 # nets_notupdated.remove(net["uuid"])
2677 # nets_updated.append(net["uuid"])
2678 # except db_base_Exception as e:
2679 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2681 # # Returns appropriate output
2682 # #print "nfvo.refresh_instance finishes"
2683 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2684 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
2685 instance_id
= instanceDict
['uuid']
2686 # if len(vms_notupdated)+len(nets_notupdated)>0:
2687 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
2688 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
2690 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2693 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2694 #print "Checking that the instance_id exists and getting the instance dictionary"
2695 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2696 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2698 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2699 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2701 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2702 myvim
= vims
.values()[0]
2705 input_vnfs
= action_dict
.pop("vnfs", [])
2706 input_vms
= action_dict
.pop("vms", [])
2707 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2711 for sce_vnf
in instanceDict
['vnfs']:
2712 for vm
in sce_vnf
['vms']:
2713 if not action_over_all
:
2714 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2715 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2718 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2719 if "console" in action_dict
:
2720 if not global_config
["http_console_proxy"]:
2721 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2722 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2723 protocol
=data
["protocol"],
2724 ip
= data
["server"],
2725 port
= data
["port"],
2726 suffix
= data
["suffix"]),
2730 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2731 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2732 "description": "this console is only reachable by local interface",
2737 #print "console data", data
2739 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2740 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2741 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2742 protocol
=data
["protocol"],
2743 ip
= global_config
["http_console_host"],
2744 port
= console_thread
.port
,
2745 suffix
= data
["suffix"]),
2749 except NfvoException
as e
:
2750 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2754 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2756 except vimconn
.vimconnException
as e
:
2757 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2760 if vm_ok
==0: #all goes wrong
2766 def create_or_use_console_proxy_thread(console_server
, console_port
):
2767 #look for a non-used port
2768 console_thread_key
= console_server
+ ":" + str(console_port
)
2769 if console_thread_key
in global_config
["console_thread"]:
2770 #global_config["console_thread"][console_thread_key].start_timeout()
2771 return global_config
["console_thread"][console_thread_key
]
2773 for port
in global_config
["console_port_iterator"]():
2774 #print "create_or_use_console_proxy_thread() port:", port
2775 if port
in global_config
["console_ports"]:
2778 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2780 global_config
["console_thread"][console_thread_key
] = clithread
2781 global_config
["console_ports"][port
] = console_thread_key
2783 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2784 #port used, try with onoher
2786 except cli
.ConsoleProxyException
as e
:
2787 raise NfvoException(str(e
), HTTP_Bad_Request
)
2788 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2791 def check_tenant(mydb
, tenant_id
):
2792 '''check that tenant exists at database'''
2793 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2795 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2799 def new_tenant(mydb
, tenant_dict
):
2800 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2804 def delete_tenant(mydb
, tenant
):
2805 #get nfvo_tenant info
2807 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2808 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2809 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2812 def new_datacenter(mydb
, datacenter_descriptor
):
2813 if "config" in datacenter_descriptor
:
2814 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2815 #Check that datacenter-type is correct
2816 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2819 module
= "vimconn_" + datacenter_type
2820 pkg
= __import__("osm_ro." + module
)
2821 vim_conn
= getattr(pkg
, module
)
2822 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
2823 except (IOError, ImportError):
2824 # if module_info and module_info[0]:
2825 # file.close(module_info[0])
2826 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2828 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2829 return datacenter_id
2832 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2833 # obtain data, check that only one exist
2834 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2837 datacenter_id
= datacenter
['uuid']
2838 where
={'uuid': datacenter
['uuid']}
2839 remove_port_mapping
= False
2840 if "config" in datacenter_descriptor
:
2841 if datacenter_descriptor
['config'] != None:
2843 new_config_dict
= datacenter_descriptor
["config"]
2846 for k
in new_config_dict
:
2847 if new_config_dict
[k
] == None:
2849 if k
== 'sdn-controller':
2850 remove_port_mapping
= True
2852 config_text
= datacenter
.get("config")
2855 config_dict
= yaml
.load(config_text
)
2856 config_dict
.update(new_config_dict
)
2860 except Exception as e
:
2861 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2863 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
2865 datacenter_descriptor
["config"] = None
2866 if remove_port_mapping
:
2868 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
2869 except ovimException
as e
:
2870 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
2872 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2873 return datacenter_id
2876 def delete_datacenter(mydb
, datacenter
):
2877 #get nfvo_tenant info
2878 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2879 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2881 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
2882 except ovimException
as e
:
2883 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
2884 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2887 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):
2888 #get datacenter info
2889 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
, vim_passwd
=vim_password
)
2890 datacenter_name
= myvim
["name"]
2892 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
2894 # get nfvo_tenant info
2895 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2896 if vim_tenant_name
==None:
2897 vim_tenant_name
=tenant_dict
['name']
2899 #check that this association does not exist before
2900 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2901 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2902 if len(tenants_datacenters
)>0:
2903 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2905 vim_tenant_id_exist_atdb
=False
2906 if not create_vim_tenant
:
2907 where_
={"datacenter_id": datacenter_id
}
2908 if vim_tenant_id
!=None:
2909 where_
["vim_tenant_id"] = vim_tenant_id
2910 if vim_tenant_name
!=None:
2911 where_
["vim_tenant_name"] = vim_tenant_name
2912 #check if vim_tenant_id is already at database
2913 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2914 if len(datacenter_tenants_dict
)>=1:
2915 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2916 vim_tenant_id_exist_atdb
=True
2917 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2919 datacenter_tenants_dict
= {}
2920 #insert at table datacenter_tenants
2921 else: #if vim_tenant_id==None:
2922 #create tenant at VIM if not provided
2924 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2925 except vimconn
.vimconnException
as e
:
2926 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2927 datacenter_tenants_dict
= {}
2928 datacenter_tenants_dict
["created"]="true"
2930 #fill datacenter_tenants table
2931 if not vim_tenant_id_exist_atdb
:
2932 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2933 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2934 datacenter_tenants_dict
["user"] = vim_username
2935 datacenter_tenants_dict
["passwd"] = vim_password
2936 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2938 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
2939 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2940 datacenter_tenants_dict
["uuid"] = id_
2942 #fill tenants_datacenters table
2943 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
2944 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
2945 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2947 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
2948 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
2949 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
2950 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
2952 thread_id
= datacenter_tenants_dict
["uuid"]
2953 vim_threads
["running"][thread_id
] = new_thread
2954 return datacenter_id
2957 def edit_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=None, vim_tenant_name
=None,
2958 vim_username
=None, vim_password
=None, config
=None):
2959 #Obtain the data of this datacenter_tenant_id
2960 vim_data
= mydb
.get_rows(
2961 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
2962 "datacenter_tenants.passwd", "datacenter_tenants.config"),
2963 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
2964 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
2965 "tenants_datacenters.datacenter_id": datacenter_id
})
2967 logger
.debug(str(vim_data
))
2968 if len(vim_data
) < 1:
2969 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
2973 v
['config'] = yaml
.load(v
['config'])
2976 v
['vim_tenant_id'] = vim_tenant_id
2978 v
['vim_tenant_name'] = vim_tenant_name
2980 v
['user'] = vim_username
2982 v
['passwd'] = vim_password
2986 v
['config'].update(config
)
2988 logger
.debug(str(v
))
2989 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
2990 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
2991 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
2993 return datacenter_id
2995 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2996 #get datacenter info
2997 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2999 #get nfvo_tenant info
3000 if not tenant_id
or tenant_id
=="any":
3003 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
3004 tenant_uuid
= tenant_dict
['uuid']
3006 #check that this association exist before
3007 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
3009 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
3010 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3011 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
3012 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
3014 #delete this association
3015 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3017 #get vim_tenant info and deletes
3019 for tenant_datacenter_item
in tenant_datacenter_list
:
3020 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
3021 #try to delete vim:tenant
3023 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
3024 if vim_tenant_dict
['created']=='true':
3025 #delete tenant at VIM if created by NFVO
3027 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
3028 except vimconn
.vimconnException
as e
:
3029 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
3030 logger
.warn(warning
)
3031 except db_base_Exception
as e
:
3032 logger
.error("Cannot delete datacenter_tenants " + str(e
))
3033 pass # the error will be caused because dependencies, vim_tenant can not be deleted
3034 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
3035 thread
= vim_threads
["running"][thread_id
]
3036 thread
.insert_task(new_task("exit", None))
3037 vim_threads
["deleting"][thread_id
] = thread
3038 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
3041 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
3043 #get datacenter info
3044 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3046 if 'net-update' in action_dict
:
3048 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
3050 except vimconn
.vimconnException
as e
:
3051 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
3052 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3053 #update nets Change from VIM format to NFVO format
3056 net_nfvo
={'datacenter_id': datacenter_id
}
3057 net_nfvo
['name'] = net
['name']
3058 #net_nfvo['description']= net['name']
3059 net_nfvo
['vim_net_id'] = net
['id']
3060 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3061 net_nfvo
['shared'] = net
['shared']
3062 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3063 net_list
.append(net_nfvo
)
3064 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
3065 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
3067 elif 'net-edit' in action_dict
:
3068 net
= action_dict
['net-edit'].pop('net')
3069 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3070 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
3071 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3073 elif 'net-delete' in action_dict
:
3074 net
= action_dict
['net-deelte'].get('net')
3075 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3076 result
= mydb
.delete_row(FROM
='datacenter_nets',
3077 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3081 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
3084 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
3085 #get datacenter info
3086 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3088 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
3089 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
3090 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
3094 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
3095 #get datacenter info
3096 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3099 action_dict
= action_dict
["netmap"]
3100 if 'vim_id' in action_dict
:
3101 filter_dict
["id"] = action_dict
['vim_id']
3102 if 'vim_name' in action_dict
:
3103 filter_dict
["name"] = action_dict
['vim_name']
3105 filter_dict
["shared"] = True
3108 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
3109 except vimconn
.vimconnException
as e
:
3110 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
3111 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3112 if len(vim_nets
)>1 and action_dict
:
3113 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
3114 elif len(vim_nets
)==0: # and action_dict:
3115 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
3117 for net
in vim_nets
:
3118 net_nfvo
={'datacenter_id': datacenter_id
}
3119 if action_dict
and "name" in action_dict
:
3120 net_nfvo
['name'] = action_dict
['name']
3122 net_nfvo
['name'] = net
['name']
3123 #net_nfvo['description']= net['name']
3124 net_nfvo
['vim_net_id'] = net
['id']
3125 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3126 net_nfvo
['shared'] = net
['shared']
3127 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3129 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
3130 net_nfvo
["status"] = "OK"
3131 net_nfvo
["uuid"] = net_id
3132 except db_base_Exception
as e
:
3136 net_nfvo
["status"] = "FAIL: " + str(e
)
3137 net_list
.append(net_nfvo
)
3140 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
3141 # obtain all network data
3143 if utils
.check_valid_uuid(network_id
):
3144 filter_dict
= {"id": network_id
}
3146 filter_dict
= {"name": network_id
}
3148 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3149 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
3150 except vimconn
.vimconnException
as e
:
3151 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
3152 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
3154 # ensure the network is defined
3155 if len(network
) == 0:
3156 raise NfvoException("Network {} is not present in the system".format(network_id
),
3159 # ensure there is only one network with the provided name
3160 if len(network
) > 1:
3161 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), HTTP_Bad_Request
)
3163 # ensure it is a dataplane network
3164 if network
[0]['type'] != 'data':
3167 # ensure we use the id
3168 network_id
= network
[0]['id']
3170 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
3171 # and with instance_scenario_id==NULL
3172 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
3173 search_dict
= {'vim_net_id': network_id
}
3176 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
3177 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
3178 except db_base_Exception
as e
:
3179 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
3180 network_id
) + str(e
), HTTP_Internal_Server_Error
)
3184 if net
['sdn_net_id'] != None:
3186 sdn_net_id
= net
['sdn_net_id']
3188 if sdn_net_counter
== 0:
3190 elif sdn_net_counter
== 1:
3193 raise NfvoException("More than one SDN network is associated to vim network {}".format(
3194 network_id
), HTTP_Internal_Server_Error
)
3196 def get_sdn_controller_id(mydb
, datacenter
):
3197 # Obtain sdn controller id
3198 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
3202 return yaml
.load(config
).get('sdn-controller')
3204 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
3206 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
3207 if not sdn_network_id
:
3208 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), HTTP_Internal_Server_Error
)
3210 #Obtain sdn controller id
3211 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
3212 if not controller_id
:
3213 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), HTTP_Internal_Server_Error
)
3215 #Obtain sdn controller info
3216 sdn_controller
= ovim
.show_of_controller(controller_id
)
3219 'name': 'external_port',
3220 'net_id': sdn_network_id
,
3221 'ofc_id': controller_id
,
3222 'switch_dpid': sdn_controller
['dpid'],
3223 'switch_port': descriptor
['port']
3226 if 'vlan' in descriptor
:
3227 port_data
['vlan'] = descriptor
['vlan']
3228 if 'mac' in descriptor
:
3229 port_data
['mac'] = descriptor
['mac']
3231 result
= ovim
.new_port(port_data
)
3232 except ovimException
as e
:
3233 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
3234 sdn_network_id
, network_id
) + str(e
), HTTP_Internal_Server_Error
)
3235 except db_base_Exception
as e
:
3236 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
3237 network_id
) + str(e
), HTTP_Internal_Server_Error
)
3239 return 'Port uuid: '+ result
3241 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
3243 filter = {'uuid': port_id
}
3245 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
3246 if not sdn_network_id
:
3247 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
3248 HTTP_Internal_Server_Error
)
3249 #in case no port_id is specified only ports marked as 'external_port' will be detached
3250 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
3253 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
3254 except ovimException
as e
:
3255 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
3256 HTTP_Internal_Server_Error
)
3258 if len(port_list
) == 0:
3259 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
3263 for port
in port_list
:
3265 port_uuid_list
.append(port
['uuid'])
3266 ovim
.delete_port(port
['uuid'])
3267 except ovimException
as e
:
3268 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), HTTP_Internal_Server_Error
)
3270 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
3272 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
3273 #get datacenter info
3274 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3277 if utils
.check_valid_uuid(name
):
3278 filter_dict
["id"] = name
3280 filter_dict
["name"] = name
3282 if item
=="networks":
3283 #filter_dict['tenant_id'] = myvim['tenant_id']
3284 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
3286 if len(content
) == 0:
3287 raise NfvoException("Network {} is not present in the system. ".format(name
),
3290 #Update the networks with the attached ports
3292 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
3293 if sdn_network_id
!= None:
3295 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
3296 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
3297 except ovimException
as e
:
3298 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), HTTP_Internal_Server_Error
)
3299 #Remove field name and if port name is external_port save it as 'type'
3300 for port
in port_list
:
3301 if port
['name'] == 'external_port':
3302 port
['type'] = "External"
3304 net
['sdn_network_id'] = sdn_network_id
3305 net
['sdn_attached_ports'] = port_list
3307 elif item
=="tenants":
3308 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
3309 elif item
== "images":
3311 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
3313 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3314 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
3315 if name
and len(content
)==1:
3316 return {item
[:-1]: content
[0]}
3317 elif name
and len(content
)==0:
3318 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
3321 return {item
: content
}
3322 except vimconn
.vimconnException
as e
:
3323 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
3324 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
3327 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
3328 #get datacenter info
3329 if tenant_id
== "any":
3332 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3334 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
3335 logger
.debug("vim_action_delete vim response: " + str(content
))
3336 items
= content
.values()[0]
3337 if type(items
)==list and len(items
)==0:
3338 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
3339 elif type(items
)==list and len(items
)>1:
3340 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
3341 else: # it is a dict
3342 item_id
= items
["id"]
3343 item_name
= str(items
.get("name"))
3346 if item
=="networks":
3347 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
3348 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
3349 if sdn_network_id
!= None:
3350 #Delete any port attachment to this network
3352 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
3353 except ovimException
as e
:
3354 raise NfvoException(
3355 "ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
3356 HTTP_Internal_Server_Error
)
3358 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
3359 for port
in port_list
:
3360 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
3362 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
3364 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id
, 'vim_net_id': item_id
})
3365 except db_base_Exception
as e
:
3366 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
3367 str(e
), HTTP_Internal_Server_Error
)
3369 #Delete the SDN network
3371 ovim
.delete_network(sdn_network_id
)
3372 except ovimException
as e
:
3373 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
3374 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
3375 HTTP_Internal_Server_Error
)
3377 content
= myvim
.delete_network(item_id
)
3378 elif item
=="tenants":
3379 content
= myvim
.delete_tenant(item_id
)
3380 elif item
== "images":
3381 content
= myvim
.delete_image(item_id
)
3383 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3384 except vimconn
.vimconnException
as e
:
3385 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
3386 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
3388 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
3391 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
3392 #get datacenter info
3393 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
3394 if tenant_id
== "any":
3396 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3398 if item
=="networks":
3399 net
= descriptor
["network"]
3400 net_name
= net
.pop("name")
3401 net_type
= net
.pop("type", "bridge")
3402 net_public
= net
.pop("shared", False)
3403 net_ipprofile
= net
.pop("ip_profile", None)
3404 net_vlan
= net
.pop("vlan", None)
3405 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
3407 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
3408 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
3411 sdn_network
['vlan'] = net_vlan
3412 sdn_network
['type'] = net_type
3413 sdn_network
['name'] = net_name
3414 ovim_content
= ovim
.new_network(sdn_network
)
3415 except ovimException
as e
:
3416 self
.logger
.error("ovimException creating SDN network={} ".format(
3417 sdn_network
) + str(e
), exc_info
=True)
3418 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
3419 HTTP_Internal_Server_Error
)
3421 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
3422 # use instance_scenario_id=None to distinguish from real instaces of nets
3423 correspondence
= {'instance_scenario_id': None, 'sdn_net_id': ovim_content
, 'vim_net_id': content
}
3424 #obtain datacenter_tenant_id
3425 correspondence
['datacenter_tenant_id'] = mydb
.get_rows(SELECT
=('uuid',), FROM
='datacenter_tenants', WHERE
={'datacenter_id': datacenter
})[0]['uuid']
3428 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
3429 except db_base_Exception
as e
:
3430 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
3431 str(e
), HTTP_Internal_Server_Error
)
3432 elif item
=="tenants":
3433 tenant
= descriptor
["tenant"]
3434 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
3436 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3437 except vimconn
.vimconnException
as e
:
3438 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
3440 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
3442 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
3443 data
= ovim
.new_of_controller(sdn_controller
)
3444 logger
.debug('New SDN controller created with uuid {}'.format(data
))
3447 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
3448 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
3449 msg
= 'SDN controller {} updated'.format(data
)
3453 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
3454 if controller_id
== None:
3455 data
= ovim
.get_of_controllers()
3457 data
= ovim
.show_of_controller(controller_id
)
3459 msg
= 'SDN controller list:\n {}'.format(data
)
3463 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
3464 select_
= ('uuid', 'config')
3465 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
3466 for datacenter
in datacenters
:
3467 if datacenter
['config']:
3468 config
= yaml
.load(datacenter
['config'])
3469 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
3470 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
3472 data
= ovim
.delete_of_controller(controller_id
)
3473 msg
= 'SDN controller {} deleted'.format(data
)
3477 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
3478 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
3479 if len(controller
) < 1:
3480 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
3483 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
3485 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
3487 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
3488 switch_dpid
= sdn_controller
["dpid"]
3491 for compute_node
in sdn_port_mapping
:
3492 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
3494 element
["compute_node"] = compute_node
["compute_node"]
3495 for port
in compute_node
["ports"]:
3496 element
["pci"] = port
.get("pci")
3497 element
["switch_port"] = port
.get("switch_port")
3498 element
["switch_mac"] = port
.get("switch_mac")
3499 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
3500 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
3501 " or 'switch_mac'", HTTP_Bad_Request
)
3502 maps
.append(dict(element
))
3504 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
3506 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
3507 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
3510 "sdn-controller": None,
3511 "datacenter-id": datacenter_id
,
3513 "ports_mapping": list()
3516 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
3517 if datacenter
['config']:
3518 config
= yaml
.load(datacenter
['config'])
3519 if 'sdn-controller' in config
:
3520 controller_id
= config
['sdn-controller']
3521 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
3522 result
["sdn-controller"] = controller_id
3523 result
["dpid"] = sdn_controller
["dpid"]
3525 if result
["sdn-controller"] == None:
3526 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), HTTP_Bad_Request
)
3527 if result
["dpid"] == None:
3528 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
3529 HTTP_Internal_Server_Error
)
3534 ports_correspondence_dict
= dict()
3536 if result
["sdn-controller"] != link
["ofc_id"]:
3537 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
3538 if result
["dpid"] != link
["switch_dpid"]:
3539 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
3541 element
["pci"] = link
["pci"]
3542 if link
["switch_port"]:
3543 element
["switch_port"] = link
["switch_port"]
3544 if link
["switch_mac"]:
3545 element
["switch_mac"] = link
["switch_mac"]
3547 if not link
["compute_node"] in ports_correspondence_dict
:
3549 content
["compute_node"] = link
["compute_node"]
3550 content
["ports"] = list()
3551 ports_correspondence_dict
[link
["compute_node"]] = content
3553 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
3555 for key
in sorted(ports_correspondence_dict
):
3556 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
3560 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
3561 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})