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
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
764 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
767 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
768 myflavorDict
["description"] = VNFCitem
["description"]
769 myflavorDict
["ram"] = vnfc
.get("ram", 0)
770 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
771 myflavorDict
["disk"] = vnfc
.get("disk", 1)
772 myflavorDict
["extended"] = {}
774 devices
= vnfc
.get("devices")
776 myflavorDict
["extended"]["devices"] = devices
779 # 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
780 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
782 # Previous code has been commented
783 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
784 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
785 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
786 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
788 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
790 # print "Error creating flavor: unknown processor model. Rollback successful."
791 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
793 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
794 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
796 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
797 myflavorDict
['extended']['numas'] = vnfc
['numas']
801 # Step 6.2 New flavors are created in the VIM
802 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
804 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
805 VNFCitem
["flavor_id"] = flavor_id
806 VNFCDict
[vnfc
['name']] = VNFCitem
808 logger
.debug("Creating new images in the VIM for each VNFC")
809 # Step 6.3 New images are created in the VIM
810 #For each VNFC, we must create the appropriate image.
811 #This "for" loop might be integrated with the previous one
812 #In case this integration is made, the VNFCDict might become a VNFClist.
813 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
814 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
816 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
817 image_dict
['universal_name']=vnfc
.get('image name')
818 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
819 image_dict
['location']=vnfc
.get('VNFC image')
820 #image_dict['new_location']=vnfc.get('image location')
821 image_dict
['checksum']=vnfc
.get('image checksum')
822 image_metadata_dict
= vnfc
.get('image metadata', None)
823 image_metadata_str
= None
824 if image_metadata_dict
is not None:
825 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
826 image_dict
['metadata']=image_metadata_str
827 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
828 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
829 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
830 VNFCDict
[vnfc
['name']]["image_id"] = image_id
831 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
832 if vnfc
.get("boot-data"):
833 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
836 # Step 7. Storing the VNF descriptor in the repository
837 if "descriptor" not in vnf_descriptor
["vnf"]:
838 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
840 # Step 8. Adding the VNF to the NFVO DB
841 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
843 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
844 _
, message
= rollback(mydb
, vims
, rollback_list
)
845 if isinstance(e
, db_base_Exception
):
846 error_text
= "Exception at database"
847 elif isinstance(e
, KeyError):
848 error_text
= "KeyError exception "
849 e
.http_code
= HTTP_Internal_Server_Error
851 error_text
= "Exception at VIM"
852 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
853 #logger.error("start_scenario %s", error_text)
854 raise NfvoException(error_text
, e
.http_code
)
857 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
860 # Step 1. Check the VNF descriptor
861 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
862 # Step 2. Check tenant exist
864 if tenant_id
!= "any":
865 check_tenant(mydb
, tenant_id
)
866 if "tenant_id" in vnf_descriptor
["vnf"]:
867 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
868 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
871 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
872 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
873 if global_config
["auto_push_VNF_to_VIMs"]:
874 vims
= get_vim(mydb
, tenant_id
)
876 # Step 4. Review the descriptor and add missing fields
877 #print vnf_descriptor
878 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
879 vnf_name
= vnf_descriptor
['vnf']['name']
880 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
881 if "physical" in vnf_descriptor
['vnf']:
882 del vnf_descriptor
['vnf']['physical']
883 #print vnf_descriptor
885 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
886 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
887 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
889 #For each VNFC, we add it to the VNFCDict and we create a flavor.
890 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
891 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
893 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
894 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
896 VNFCitem
["name"] = vnfc
['name']
897 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
899 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
902 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
903 myflavorDict
["description"] = VNFCitem
["description"]
904 myflavorDict
["ram"] = vnfc
.get("ram", 0)
905 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
906 myflavorDict
["disk"] = vnfc
.get("disk", 1)
907 myflavorDict
["extended"] = {}
909 devices
= vnfc
.get("devices")
911 myflavorDict
["extended"]["devices"] = devices
914 # 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
915 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
917 # Previous code has been commented
918 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
919 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
920 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
921 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
923 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
925 # print "Error creating flavor: unknown processor model. Rollback successful."
926 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
928 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
929 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
931 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
932 myflavorDict
['extended']['numas'] = vnfc
['numas']
936 # Step 6.2 New flavors are created in the VIM
937 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
939 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
940 VNFCitem
["flavor_id"] = flavor_id
941 VNFCDict
[vnfc
['name']] = VNFCitem
943 logger
.debug("Creating new images in the VIM for each VNFC")
944 # Step 6.3 New images are created in the VIM
945 #For each VNFC, we must create the appropriate image.
946 #This "for" loop might be integrated with the previous one
947 #In case this integration is made, the VNFCDict might become a VNFClist.
948 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
949 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
951 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
952 image_dict
['universal_name']=vnfc
.get('image name')
953 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
954 image_dict
['location']=vnfc
.get('VNFC image')
955 #image_dict['new_location']=vnfc.get('image location')
956 image_dict
['checksum']=vnfc
.get('image checksum')
957 image_metadata_dict
= vnfc
.get('image metadata', None)
958 image_metadata_str
= None
959 if image_metadata_dict
is not None:
960 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
961 image_dict
['metadata']=image_metadata_str
962 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
963 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
964 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
965 VNFCDict
[vnfc
['name']]["image_id"] = image_id
966 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
967 if vnfc
.get("boot-data"):
968 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
970 # Step 7. Storing the VNF descriptor in the repository
971 if "descriptor" not in vnf_descriptor
["vnf"]:
972 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
974 # Step 8. Adding the VNF to the NFVO DB
975 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
977 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
978 _
, message
= rollback(mydb
, vims
, rollback_list
)
979 if isinstance(e
, db_base_Exception
):
980 error_text
= "Exception at database"
981 elif isinstance(e
, KeyError):
982 error_text
= "KeyError exception "
983 e
.http_code
= HTTP_Internal_Server_Error
985 error_text
= "Exception at VIM"
986 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
987 #logger.error("start_scenario %s", error_text)
988 raise NfvoException(error_text
, e
.http_code
)
991 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
992 #check valid tenant_id
993 check_tenant(mydb
, tenant_id
)
996 if tenant_id
!= "any":
997 where_or
["tenant_id"] = tenant_id
998 where_or
["public"] = True
999 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1002 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
1003 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
1004 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1005 data
={'vnf' : filtered_content
}
1007 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1008 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description', 'boot_data'),
1009 WHERE
={'vnfs.uuid': vnf_id
} )
1011 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1012 # change boot_data into boot-data
1014 if vm
.get("boot_data"):
1015 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1018 data
['vnf']['VNFC'] = content
1019 #TODO: GET all the information from a VNFC and include it in the output.
1022 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1023 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1024 WHERE
={'vnfs.uuid': vnf_id
} )
1025 data
['vnf']['nets'] = content
1027 #GET ip-profile for each net
1028 for net
in data
['vnf']['nets']:
1029 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1030 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1031 WHERE
={'net_id': net
["uuid"]} )
1032 if len(ipprofiles
)==1:
1033 net
["ip_profile"] = ipprofiles
[0]
1034 elif len(ipprofiles
)>1:
1035 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
1038 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1040 #GET External Interfaces
1041 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1042 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1043 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1044 WHERE
={'vnfs.uuid': vnf_id
},
1045 WHERE_NOT
={'interfaces.external_name': None} )
1047 data
['vnf']['external-connections'] = content
1052 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1053 # Check tenant exist
1054 if tenant_id
!= "any":
1055 check_tenant(mydb
, tenant_id
)
1056 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1057 vims
= get_vim(mydb
, tenant_id
)
1061 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1063 if tenant_id
!= "any":
1064 where_or
["tenant_id"] = tenant_id
1065 where_or
["public"] = True
1066 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1067 vnf_id
= vnf
["uuid"]
1069 # "Getting the list of flavors and tenants of the VNF"
1070 flavorList
= get_flavorlist(mydb
, vnf_id
)
1071 if len(flavorList
)==0:
1072 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1074 imageList
= get_imagelist(mydb
, vnf_id
)
1075 if len(imageList
)==0:
1076 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1078 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1080 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1083 for flavor
in flavorList
:
1084 #check if flavor is used by other vnf
1086 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1088 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1090 #flavor not used, must be deleted
1092 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
1093 for flavor_vim
in c
:
1094 if flavor_vim
["datacenter_id"] not in vims
:
1096 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
1098 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
1100 myvim
.delete_flavor(flavor_vim
["vim_id"])
1101 except vimconn
.vimconnNotFoundException
as e
:
1102 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
1103 except vimconn
.vimconnException
as e
:
1104 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1105 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1106 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
1107 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1108 mydb
.delete_row_by_id('flavors', flavor
)
1109 except db_base_Exception
as e
:
1110 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1111 undeletedItems
.append("flavor %s" % flavor
)
1114 for image
in imageList
:
1116 #check if image is used by other vnf
1117 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1119 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1121 #image not used, must be deleted
1123 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1125 if image_vim
["datacenter_id"] not in vims
:
1127 if image_vim
['created']=='false': #skip this image because not created by openmano
1129 myvim
=vims
[ image_vim
["datacenter_id"] ]
1131 myvim
.delete_image(image_vim
["vim_id"])
1132 except vimconn
.vimconnNotFoundException
as e
:
1133 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1134 except vimconn
.vimconnException
as e
:
1135 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1136 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1137 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1138 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1139 mydb
.delete_row_by_id('images', image
)
1140 except db_base_Exception
as e
:
1141 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1142 undeletedItems
.append("image %s" % image
)
1144 return vnf_id
+ " " + vnf
["name"]
1146 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1149 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1150 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1154 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1155 myvim
= vims
.values()[0]
1156 result
,servers
= myvim
.get_hosts_info()
1158 return result
, servers
1159 topology
= {'name':myvim
['name'] , 'servers': servers
}
1160 return result
, topology
1163 def get_hosts(mydb
, nfvo_tenant_id
):
1164 vims
= get_vim(mydb
, nfvo_tenant_id
)
1166 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1168 #print "nfvo.datacenter_action() error. Several datacenters found"
1169 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1170 myvim
= vims
.values()[0]
1172 hosts
= myvim
.get_hosts()
1173 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1175 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1177 server
={'name':host
['name'], 'vms':[]}
1178 for vm
in host
['instances']:
1179 #get internal name and model
1181 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1182 WHERE
={'vim_vm_id':vm
['id']} )
1184 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1186 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1188 except db_base_Exception
as e
:
1189 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1190 datacenter
['Datacenters'][0]['servers'].append(server
)
1191 #return -400, "en construccion"
1193 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1195 except vimconn
.vimconnException
as e
:
1196 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1199 def new_scenario(mydb
, tenant_id
, topo
):
1201 # result, vims = get_vim(mydb, tenant_id)
1203 # return result, vims
1205 if tenant_id
!= "any":
1206 check_tenant(mydb
, tenant_id
)
1207 if "tenant_id" in topo
:
1208 if topo
["tenant_id"] != tenant_id
:
1209 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1214 #1.1: get VNFs and external_networks (other_nets).
1216 other_nets
={} #external_networks, bridge_networks and data_networkds
1217 nodes
= topo
['topology']['nodes']
1218 for k
in nodes
.keys():
1219 if nodes
[k
]['type'] == 'VNF':
1221 vnfs
[k
]['ifaces'] = {}
1222 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1223 other_nets
[k
] = nodes
[k
]
1224 other_nets
[k
]['external']=True
1225 elif nodes
[k
]['type'] == 'network':
1226 other_nets
[k
] = nodes
[k
]
1227 other_nets
[k
]['external']=False
1230 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1231 for name
,vnf
in vnfs
.items():
1233 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1235 error_pos
= "'topology':'nodes':'" + name
+ "'"
1237 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1238 where
['uuid'] = vnf
['vnf_id']
1239 if 'VNF model' in vnf
:
1240 error_text
+= " 'VNF model' " + vnf
['VNF model']
1241 where
['name'] = vnf
['VNF model']
1243 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1245 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1251 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1253 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1254 vnf
['uuid']=vnf_db
[0]['uuid']
1255 vnf
['description']=vnf_db
[0]['description']
1256 #get external interfaces
1257 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1258 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1259 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1260 for ext_iface
in ext_ifaces
:
1261 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1263 #1.4 get list of connections
1264 conections
= topo
['topology']['connections']
1265 conections_list
= []
1266 conections_list_name
= []
1267 for k
in conections
.keys():
1268 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1269 ifaces_list
= conections
[k
]['nodes'].items()
1270 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1272 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1273 for k2
in conection_pair_list
:
1276 con_type
= conections
[k
].get("type", "link")
1277 if con_type
!= "link":
1279 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1280 other_nets
[k
] = {'external': False}
1281 if conections
[k
].get("graph"):
1282 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1283 ifaces_list
.append( (k
, None) )
1286 if con_type
== "external_network":
1287 other_nets
[k
]['external'] = True
1288 if conections
[k
].get("model"):
1289 other_nets
[k
]["model"] = conections
[k
]["model"]
1291 other_nets
[k
]["model"] = k
1292 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1293 other_nets
[k
]["model"] = con_type
1295 conections_list_name
.append(k
)
1296 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)
1297 #print set(ifaces_list)
1298 #check valid VNF and iface names
1299 for iface
in ifaces_list
:
1300 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1301 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1302 str(k
), iface
[0]), HTTP_Not_Found
)
1303 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1304 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1305 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1307 #1.5 unify connections from the pair list to a consolidated list
1309 while index
< len(conections_list
):
1311 while index2
< len(conections_list
):
1312 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1313 conections_list
[index
] |
= conections_list
[index2
]
1314 del conections_list
[index2
]
1315 del conections_list_name
[index2
]
1318 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1320 #for k in conections_list:
1325 #1.6 Delete non external nets
1326 # for k in other_nets.keys():
1327 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1328 # for con in conections_list:
1330 # for index in range(0,len(con)):
1331 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1332 # for index in delete_indexes:
1335 #1.7: Check external_ports are present at database table datacenter_nets
1336 for k
,net
in other_nets
.items():
1337 error_pos
= "'topology':'nodes':'" + k
+ "'"
1338 if net
['external']==False:
1339 if 'name' not in net
:
1341 if 'model' not in net
:
1342 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1343 if net
['model']=='bridge_net':
1344 net
['type']='bridge';
1345 elif net
['model']=='dataplane_net':
1348 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1350 #IF we do not want to check that external network exist at datacenter
1355 # if 'net_id' in net:
1356 # error_text += " 'net_id' " + net['net_id']
1357 # WHERE_['uuid'] = net['net_id']
1358 # if 'model' in net:
1359 # error_text += " 'model' " + net['model']
1360 # WHERE_['name'] = net['model']
1361 # if len(WHERE_) == 0:
1362 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1363 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1364 # FROM='datacenter_nets', WHERE=WHERE_ )
1366 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1368 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1369 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1371 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1372 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1373 # other_nets[k].update(net_db[0])
1376 net_nb
=0 #Number of nets
1377 for con
in conections_list
:
1378 #check if this is connected to a external net
1382 for index
in range(0,len(con
)):
1383 #check if this is connected to a external net
1384 for net_key
in other_nets
.keys():
1385 if con
[index
][0]==net_key
:
1386 if other_net_index
>=0:
1387 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1388 #print "nfvo.new_scenario " + error_text
1389 raise NfvoException(error_text
, HTTP_Bad_Request
)
1391 other_net_index
= index
1392 net_target
= net_key
1394 #print "other_net_index", other_net_index
1396 if other_net_index
>=0:
1397 del con
[other_net_index
]
1398 #IF we do not want to check that external network exist at datacenter
1399 if other_nets
[net_target
]['external'] :
1400 if "name" not in other_nets
[net_target
]:
1401 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1402 if other_nets
[net_target
]["type"] == "external_network":
1403 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1404 other_nets
[net_target
]["type"] = "data"
1406 other_nets
[net_target
]["type"] = "bridge"
1408 # if other_nets[net_target]['external'] :
1409 # 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
1410 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1411 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1412 # print "nfvo.new_scenario " + error_text
1413 # return -HTTP_Bad_Request, error_text
1416 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1419 net_type_bridge
=False
1421 net_target
= "__-__net"+str(net_nb
)
1422 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1423 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1426 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1427 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1428 if iface_type
=='mgmt' or iface_type
=='bridge':
1429 net_type_bridge
= True
1431 net_type_data
= True
1432 if net_type_bridge
and net_type_data
:
1433 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1434 #print "nfvo.new_scenario " + error_text
1435 raise NfvoException(error_text
, HTTP_Bad_Request
)
1436 elif net_type_bridge
:
1439 type_
='data' if len(con
)>2 else 'ptp'
1440 net_list
[net_target
]['type'] = type_
1443 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1444 #print "nfvo.new_scenario " + error_text
1446 raise NfvoException(error_text
, HTTP_Bad_Request
)
1448 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1449 #1.8.1 obtain management net
1450 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1451 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1452 #1.8.2 check all interfaces from all vnfs
1454 add_mgmt_net
= False
1455 for vnf
in vnfs
.values():
1456 for iface
in vnf
['ifaces'].values():
1457 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1458 #iface not connected
1459 iface
['net_key'] = 'mgmt'
1461 if add_mgmt_net
and 'mgmt' not in net_list
:
1462 net_list
['mgmt']=mgmt_net
[0]
1463 net_list
['mgmt']['external']=True
1464 net_list
['mgmt']['graph']={'visible':False}
1466 net_list
.update(other_nets
)
1468 #print 'net_list', net_list
1473 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1474 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1475 'tenant_id':tenant_id
, 'name':topo
['name'],
1476 'description':topo
.get('description',topo
['name']),
1477 'public': topo
.get('public', False)
1483 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
1484 """ This creates a new scenario for version 0.2 and 0.3"""
1485 scenario
= scenario_dict
["scenario"]
1486 if tenant_id
!= "any":
1487 check_tenant(mydb
, tenant_id
)
1488 if "tenant_id" in scenario
:
1489 if scenario
["tenant_id"] != tenant_id
:
1490 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1491 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1492 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1496 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
1497 for name
,vnf
in scenario
["vnfs"].iteritems():
1499 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1501 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1503 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1504 where
['uuid'] = vnf
['vnf_id']
1505 if 'vnf_name' in vnf
:
1506 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1507 where
['name'] = vnf
['vnf_name']
1509 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1510 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
1515 if len(vnf_db
) == 0:
1516 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1517 elif len(vnf_db
) > 1:
1518 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1519 vnf
['uuid'] = vnf_db
[0]['uuid']
1520 vnf
['description'] = vnf_db
[0]['description']
1522 # get external interfaces
1523 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
1524 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1525 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name': None} )
1526 for ext_iface
in ext_ifaces
:
1527 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
1528 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1530 # 2: Insert net_key and ip_address at every vnf interface
1531 for net_name
, net
in scenario
["networks"].items():
1532 net_type_bridge
= False
1533 net_type_data
= False
1534 for iface_dict
in net
["interfaces"]:
1535 if version
== "0.2":
1536 temp_dict
= iface_dict
1538 elif version
== "0.3":
1539 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
1540 ip_address
= iface_dict
.get('ip_address', None)
1541 for vnf
, iface
in temp_dict
.items():
1542 if vnf
not in scenario
["vnfs"]:
1543 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
1545 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1546 raise NfvoException(error_text
, HTTP_Not_Found
)
1547 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1548 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
1549 .format(net_name
, iface
)
1550 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1551 raise NfvoException(error_text
, HTTP_Bad_Request
)
1552 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1553 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
1554 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1555 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1556 raise NfvoException(error_text
, HTTP_Bad_Request
)
1557 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1558 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
1559 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1560 if iface_type
== 'mgmt' or iface_type
== 'bridge':
1561 net_type_bridge
= True
1563 net_type_data
= True
1565 if net_type_bridge
and net_type_data
:
1566 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
1568 # logger.debug("nfvo.new_scenario " + error_text)
1569 raise NfvoException(error_text
, HTTP_Bad_Request
)
1570 elif net_type_bridge
:
1573 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
1575 if net
.get("implementation"): # for v0.3
1576 if type_
== "bridge" and net
["implementation"] == "underlay":
1577 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
1578 "'network':'{}'".format(net_name
)
1579 # logger.debug(error_text)
1580 raise NfvoException(error_text
, HTTP_Bad_Request
)
1581 elif type_
!= "bridge" and net
["implementation"] == "overlay":
1582 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
1583 "'network':'{}'".format(net_name
)
1584 # logger.debug(error_text)
1585 raise NfvoException(error_text
, HTTP_Bad_Request
)
1586 net
.pop("implementation")
1587 if "type" in net
and version
== "0.3": # for v0.3
1588 if type_
== "data" and net
["type"] == "e-line":
1589 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
1590 "'e-line' at 'network':'{}'".format(net_name
)
1591 # logger.debug(error_text)
1592 raise NfvoException(error_text
, HTTP_Bad_Request
)
1593 elif type_
== "ptp" and net
["type"] == "e-lan":
1597 net
['name'] = net_name
1598 net
['external'] = net
.get('external', False)
1600 # 3: insert at database
1601 scenario
["nets"] = scenario
["networks"]
1602 scenario
['tenant_id'] = tenant_id
1603 scenario_id
= mydb
.new_scenario(scenario
)
1607 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1608 data
["uuid"] = scenario_id
1609 data
["tenant_id"] = tenant_id
1610 c
= mydb
.edit_scenario( data
)
1614 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1615 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1616 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
1617 vims
= {datacenter_id
: myvim
}
1618 myvim_tenant
= myvim
['tenant_id']
1619 datacenter_name
= myvim
['name']
1623 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1624 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1625 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
1626 scenarioDict
['datacenter_id'] = datacenter_id
1627 #print '================scenarioDict======================='
1628 #print json.dumps(scenarioDict, indent=4)
1629 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1631 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1632 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1634 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1635 auxNetDict
['scenario'] = {}
1637 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1638 for sce_net
in scenarioDict
['nets']:
1639 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1641 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1642 myNetName
= myNetName
[0:255] #limit length
1643 myNetType
= sce_net
['type']
1645 myNetDict
["name"] = myNetName
1646 myNetDict
["type"] = myNetType
1647 myNetDict
["tenant_id"] = myvim_tenant
1648 myNetIPProfile
= sce_net
.get('ip_profile', None)
1650 #We should use the dictionary as input parameter for new_network
1652 if not sce_net
["external"]:
1653 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1654 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1655 sce_net
['vim_id'] = network_id
1656 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1657 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1658 sce_net
["created"] = True
1660 if sce_net
['vim_id'] == None:
1661 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1662 _
, message
= rollback(mydb
, vims
, rollbackList
)
1663 logger
.error("nfvo.start_scenario: %s", error_text
)
1664 raise NfvoException(error_text
, HTTP_Bad_Request
)
1665 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1666 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1668 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1669 #For each vnf net, we create it and we add it to instanceNetlist.
1670 for sce_vnf
in scenarioDict
['vnfs']:
1671 for net
in sce_vnf
['nets']:
1672 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1674 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1675 myNetName
= myNetName
[0:255] #limit length
1676 myNetType
= net
['type']
1678 myNetDict
["name"] = myNetName
1679 myNetDict
["type"] = myNetType
1680 myNetDict
["tenant_id"] = myvim_tenant
1681 myNetIPProfile
= net
.get('ip_profile', None)
1684 #We should use the dictionary as input parameter for new_network
1685 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1686 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1687 net
['vim_id'] = network_id
1688 if sce_vnf
['uuid'] not in auxNetDict
:
1689 auxNetDict
[sce_vnf
['uuid']] = {}
1690 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1691 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1692 net
["created"] = True
1694 #print "auxNetDict:"
1695 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1697 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1698 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1700 for sce_vnf
in scenarioDict
['vnfs']:
1701 for vm
in sce_vnf
['vms']:
1704 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1705 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
1706 #myVMDict['description'] = vm['description']
1707 myVMDict
['description'] = myVMDict
['name'][0:99]
1709 myVMDict
['start'] = "no"
1710 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1711 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1713 #create image at vim in case it not exist
1714 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1715 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1716 vm
['vim_image_id'] = image_id
1718 #create flavor at vim in case it not exist
1719 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1720 if flavor_dict
['extended']!=None:
1721 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1722 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1723 vm
['vim_flavor_id'] = flavor_id
1726 myVMDict
['imageRef'] = vm
['vim_image_id']
1727 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1728 myVMDict
['networks'] = []
1729 for iface
in vm
['interfaces']:
1731 if iface
['type']=="data":
1732 netDict
['type'] = iface
['model']
1733 elif "model" in iface
and iface
["model"]!=None:
1734 netDict
['model']=iface
['model']
1735 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1736 #discover type of interface looking at flavor
1737 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1738 for flavor_iface
in numa
.get('interfaces',[]):
1739 if flavor_iface
.get('name') == iface
['internal_name']:
1740 if flavor_iface
['dedicated'] == 'yes':
1741 netDict
['type']="PF" #passthrough
1742 elif flavor_iface
['dedicated'] == 'no':
1743 netDict
['type']="VF" #siov
1744 elif flavor_iface
['dedicated'] == 'yes:sriov':
1745 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1746 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1748 netDict
["use"]=iface
['type']
1749 if netDict
["use"]=="data" and not netDict
.get("type"):
1750 #print "netDict", netDict
1751 #print "iface", iface
1752 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'])
1753 if flavor_dict
.get('extended')==None:
1754 raise NfvoException(e_text
+ "After database migration some information is not available. \
1755 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1757 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1758 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1759 netDict
["type"]="virtual"
1760 if "vpci" in iface
and iface
["vpci"] is not None:
1761 netDict
['vpci'] = iface
['vpci']
1762 if "mac" in iface
and iface
["mac"] is not None:
1763 netDict
['mac_address'] = iface
['mac']
1764 if "port-security" in iface
and iface
["port-security"] is not None:
1765 netDict
['port_security'] = iface
['port-security']
1766 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
1767 netDict
['floating_ip'] = iface
['floating-ip']
1768 netDict
['name'] = iface
['internal_name']
1769 if iface
['net_id'] is None:
1770 for vnf_iface
in sce_vnf
["interfaces"]:
1773 if vnf_iface
['interface_id']==iface
['uuid']:
1774 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1777 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1778 #skip bridge ifaces not connected to any net
1779 #if 'net_id' not in netDict or netDict['net_id']==None:
1781 myVMDict
['networks'].append(netDict
)
1782 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1783 #print myVMDict['name']
1784 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1785 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1786 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1787 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1788 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1789 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1790 vm
['vim_id'] = vm_id
1791 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1792 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1793 for net
in myVMDict
['networks']:
1795 for iface
in vm
['interfaces']:
1796 if net
["name"]==iface
["internal_name"]:
1797 iface
["vim_id"]=net
["vim_id"]
1800 logger
.debug("start scenario Deployment done")
1801 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1802 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1803 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1804 return mydb
.get_instance_scenario(instance_id
)
1806 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1807 _
, message
= rollback(mydb
, vims
, rollbackList
)
1808 if isinstance(e
, db_base_Exception
):
1809 error_text
= "Exception at database"
1811 error_text
= "Exception at VIM"
1812 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1813 #logger.error("start_scenario %s", error_text)
1814 raise NfvoException(error_text
, e
.http_code
)
1817 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
1818 ''' join the cloud config information into cloud_config_preserve.
1819 In case of conflict cloud_config_preserve preserves
1822 if not cloud_config_preserve
and not cloud_config
:
1825 new_cloud_config
= {"key-pairs":[], "users":[]}
1827 if cloud_config_preserve
:
1828 for key
in cloud_config_preserve
.get("key-pairs", () ):
1829 if key
not in new_cloud_config
["key-pairs"]:
1830 new_cloud_config
["key-pairs"].append(key
)
1832 for key
in cloud_config
.get("key-pairs", () ):
1833 if key
not in new_cloud_config
["key-pairs"]:
1834 new_cloud_config
["key-pairs"].append(key
)
1835 if not new_cloud_config
["key-pairs"]:
1836 del new_cloud_config
["key-pairs"]
1840 new_cloud_config
["users"] += cloud_config
.get("users", () )
1841 if cloud_config_preserve
:
1842 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
1843 index_to_delete
= []
1844 users
= new_cloud_config
.get("users", [])
1845 for index0
in range(0,len(users
)):
1846 if index0
in index_to_delete
:
1848 for index1
in range(index0
+1,len(users
)):
1849 if index1
in index_to_delete
:
1851 if users
[index0
]["name"] == users
[index1
]["name"]:
1852 index_to_delete
.append(index1
)
1853 for key
in users
[index1
].get("key-pairs",()):
1854 if "key-pairs" not in users
[index0
]:
1855 users
[index0
]["key-pairs"] = [key
]
1856 elif key
not in users
[index0
]["key-pairs"]:
1857 users
[index0
]["key-pairs"].append(key
)
1858 index_to_delete
.sort(reverse
=True)
1859 for index
in index_to_delete
:
1861 if not new_cloud_config
["users"]:
1862 del new_cloud_config
["users"]
1865 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
1866 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
1867 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
1868 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
1871 if cloud_config
and cloud_config
.get("user-data") != None:
1872 new_cloud_config
["user-data"] = cloud_config
["user-data"]
1873 if cloud_config_preserve
and cloud_config_preserve
.get("user-data") != None:
1874 new_cloud_config
["user-data"] = cloud_config_preserve
["user-data"]
1877 new_cloud_config
["config-files"] = []
1878 if cloud_config
and cloud_config
.get("config-files") != None:
1879 new_cloud_config
["config-files"] += cloud_config
["config-files"]
1880 if cloud_config_preserve
:
1881 for file in cloud_config_preserve
.get("config-files", ()):
1882 for index
in range(0, len(new_cloud_config
["config-files"])):
1883 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
1884 new_cloud_config
["config-files"][index
] = file
1887 new_cloud_config
["config-files"].append(file)
1888 if not new_cloud_config
["config-files"]:
1889 del new_cloud_config
["config-files"]
1890 return new_cloud_config
1893 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
1894 datacenter_id
= None
1895 datacenter_name
= None
1898 if datacenter_tenant_id
:
1899 thread_id
= datacenter_tenant_id
1900 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
1902 where_
={"td.nfvo_tenant_id": tenant_id
}
1903 if datacenter_id_name
:
1904 if utils
.check_valid_uuid(datacenter_id_name
):
1905 datacenter_id
= datacenter_id_name
1906 where_
["dt.datacenter_id"] = datacenter_id
1908 datacenter_name
= datacenter_id_name
1909 where_
["d.name"] = datacenter_name
1910 if datacenter_tenant_id
:
1911 where_
["dt.uuid"] = datacenter_tenant_id
1912 datacenters
= mydb
.get_rows(
1913 SELECT
=("dt.uuid as datacenter_tenant_id",),
1914 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
1915 "join datacenters as d on d.uuid=dt.datacenter_id",
1917 if len(datacenters
) > 1:
1918 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1920 thread_id
= datacenters
[0]["datacenter_tenant_id"]
1921 thread
= vim_threads
["running"].get(thread_id
)
1923 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1924 return thread_id
, thread
1925 except db_base_Exception
as e
:
1926 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
1929 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1930 datacenter_id
= None
1931 datacenter_name
= None
1932 if datacenter_id_name
:
1933 if utils
.check_valid_uuid(datacenter_id_name
):
1934 datacenter_id
= datacenter_id_name
1936 datacenter_name
= datacenter_id_name
1937 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1939 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1941 #print "nfvo.datacenter_action() error. Several datacenters found"
1942 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1943 return vims
.keys()[0], vims
.values()[0]
1947 '''Takes dict d and updates it with the values in dict u.'''
1948 '''It merges all depth levels'''
1949 for k
, v
in u
.iteritems():
1950 if isinstance(v
, collections
.Mapping
):
1951 r
= update(d
.get(k
, {}), v
)
1958 def create_instance(mydb
, tenant_id
, instance_dict
):
1959 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1960 # logger.debug("Creating instance...")
1961 scenario
= instance_dict
["scenario"]
1963 #find main datacenter
1965 myvim_threads_id
= {}
1968 datacenter
= instance_dict
.get("datacenter")
1969 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1970 myvims
[default_datacenter_id
] = vim
1971 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
1972 tasks_to_launch
[myvim_threads_id
[default_datacenter_id
]] = []
1973 #myvim_tenant = myvim['tenant_id']
1974 # default_datacenter_name = vim['name']
1977 #print "Checking that the scenario exists and getting the scenario dictionary"
1978 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1980 #logger.debug(">>>>>>> Dictionaries before merging")
1981 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1982 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1984 scenarioDict
['datacenter_id'] = default_datacenter_id
1986 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1987 auxNetDict
['scenario'] = {}
1989 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1990 instance_name
= instance_dict
["name"]
1991 instance_description
= instance_dict
.get("description")
1993 # 0 check correct parameters
1994 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1996 for scenario_net
in scenarioDict
['nets']:
1997 if net_name
== scenario_net
["name"]:
2001 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
2002 if "sites" not in net_instance_desc
:
2003 net_instance_desc
["sites"] = [ {} ]
2004 site_without_datacenter_field
= False
2005 for site
in net_instance_desc
["sites"]:
2006 if site
.get("datacenter"):
2007 if site
["datacenter"] not in myvims
:
2008 #Add this datacenter to myvims
2009 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
2011 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
2012 tasks_to_launch
[myvim_threads_id
[d
]] = []
2013 site
["datacenter"] = d
#change name to id
2015 if site_without_datacenter_field
:
2016 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
2017 site_without_datacenter_field
= True
2018 site
["datacenter"] = default_datacenter_id
#change name to id
2020 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
2022 for scenario_vnf
in scenarioDict
['vnfs']:
2023 if vnf_name
== scenario_vnf
['name']:
2027 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
2028 if "datacenter" in vnf_instance_desc
:
2029 # Add this datacenter to myvims
2030 if vnf_instance_desc
["datacenter"] not in myvims
:
2031 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2033 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2034 tasks_to_launch
[myvim_threads_id
[d
]] = []
2035 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2037 #0.1 parse cloud-config parameters
2038 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2040 #0.2 merge instance information into scenario
2041 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2042 #However, this is not possible yet.
2043 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2044 for scenario_net
in scenarioDict
['nets']:
2045 if net_name
== scenario_net
["name"]:
2046 if 'ip-profile' in net_instance_desc
:
2047 # translate from input format to database format
2048 ipprofile_in
= net_instance_desc
['ip-profile']
2050 ipprofile_db
['subnet_address'] = ipprofile_in
.get('subnet-address')
2051 ipprofile_db
['ip_version'] = ipprofile_in
.get('ip-version', 'IPv4')
2052 ipprofile_db
['gateway_address'] = ipprofile_in
.get('gateway-address')
2053 ipprofile_db
['dns_address'] = ipprofile_in
.get('dns-address')
2054 if isinstance(ipprofile_db
['dns_address'], (list, tuple)):
2055 ipprofile_db
['dns_address'] = ";".join(ipprofile_db
['dns_address'])
2056 if 'dhcp' in ipprofile_in
:
2057 ipprofile_db
['dhcp_start_address'] = ipprofile_in
['dhcp'].get('start-address')
2058 ipprofile_db
['dhcp_enabled'] = ipprofile_in
['dhcp'].get('enabled', True)
2059 ipprofile_db
['dhcp_count'] = ipprofile_in
['dhcp'].get('count' )
2060 if 'ip_profile' not in scenario_net
:
2061 scenario_net
['ip_profile'] = ipprofile_db
2063 update(scenario_net
['ip_profile'], ipprofile_db
)
2064 for interface
in net_instance_desc
.get('interfaces', () ):
2065 if 'ip_address' in interface
:
2066 for vnf
in scenarioDict
['vnfs']:
2067 if interface
['vnf'] == vnf
['name']:
2068 for vnf_interface
in vnf
['interfaces']:
2069 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2070 vnf_interface
['ip_address']=interface
['ip_address']
2072 #logger.debug(">>>>>>>> Merged dictionary")
2073 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
2076 # 1. Creating new nets (sce_nets) in the VIM"
2077 for sce_net
in scenarioDict
['nets']:
2078 sce_net
["vim_id_sites"]={}
2079 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
2080 net_name
= descriptor_net
.get("vim-network-name")
2081 auxNetDict
['scenario'][sce_net
['uuid']] = {}
2083 sites
= descriptor_net
.get("sites", [ {} ])
2085 if site
.get("datacenter"):
2086 vim
= myvims
[ site
["datacenter"] ]
2087 datacenter_id
= site
["datacenter"]
2088 myvim_thread_id
= myvim_threads_id
[ site
["datacenter"] ]
2090 vim
= myvims
[ default_datacenter_id
]
2091 datacenter_id
= default_datacenter_id
2092 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2093 net_type
= sce_net
['type']
2094 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
2095 if sce_net
["external"]:
2097 net_name
= sce_net
["name"]
2098 if "netmap-use" in site
or "netmap-create" in site
:
2099 create_network
= False
2100 lookfor_network
= False
2101 if "netmap-use" in site
:
2102 lookfor_network
= True
2103 if utils
.check_valid_uuid(site
["netmap-use"]):
2104 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2105 lookfor_filter
["id"] = site
["netmap-use"]
2107 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2108 lookfor_filter
["name"] = site
["netmap-use"]
2109 if "netmap-create" in site
:
2110 create_network
= True
2111 net_vim_name
= net_name
2112 if site
["netmap-create"]:
2113 net_vim_name
= site
["netmap-create"]
2115 elif sce_net
['vim_id'] != None:
2116 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
2117 create_network
= False
2118 lookfor_network
= True
2119 lookfor_filter
["id"] = sce_net
['vim_id']
2120 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
2121 #look for network at datacenter and return error
2123 #There is not a netmap, look at datacenter for a net with this name and create if not found
2124 create_network
= True
2125 lookfor_network
= True
2126 lookfor_filter
["name"] = sce_net
["name"]
2127 net_vim_name
= sce_net
["name"]
2128 filter_text
= "scenario name '%s'" % sce_net
["name"]
2131 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
2132 net_name
= net_name
[:255] #limit length
2133 net_vim_name
= net_name
2134 create_network
= True
2135 lookfor_network
= False
2138 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
2139 if len(vim_nets
) > 1:
2140 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2141 elif len(vim_nets
) == 0:
2142 if not create_network
:
2143 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2145 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
2146 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
2147 create_network
= False
2149 #if network is not external
2150 task
= new_task("new-net", (net_vim_name
, net_type
, sce_net
.get('ip_profile',None)))
2151 task_id
= task
["id"]
2152 instance_tasks
[task_id
] = task
2153 tasks_to_launch
[myvim_thread_id
].append(task
)
2154 #network_id = vim.new_network(net_vim_name, net_type, sce_net.get('ip_profile',None))
2155 sce_net
["vim_id_sites"][datacenter_id
] = task_id
2156 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = task_id
2157 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':task_id
})
2158 sce_net
["created"] = True
2160 # 2. Creating new nets (vnf internal nets) in the VIM"
2161 #For each vnf net, we create it and we add it to instanceNetlist.
2162 for sce_vnf
in scenarioDict
['vnfs']:
2163 for net
in sce_vnf
['nets']:
2164 if sce_vnf
.get("datacenter"):
2165 vim
= myvims
[ sce_vnf
["datacenter"] ]
2166 datacenter_id
= sce_vnf
["datacenter"]
2167 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"]]
2169 vim
= myvims
[ default_datacenter_id
]
2170 datacenter_id
= default_datacenter_id
2171 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2172 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
2173 net_name
= descriptor_net
.get("name")
2175 net_name
= "%s.%s" %(instance_name
, net
["name"])
2176 net_name
= net_name
[:255] #limit length
2177 net_type
= net
['type']
2178 task
= new_task("new-net", (net_name
, net_type
, net
.get('ip_profile',None)))
2179 task_id
= task
["id"]
2180 instance_tasks
[task_id
] = task
2181 tasks_to_launch
[myvim_thread_id
].append(task
)
2182 # network_id = vim.new_network(net_name, net_type, net.get('ip_profile',None))
2183 net
['vim_id'] = task_id
2184 if sce_vnf
['uuid'] not in auxNetDict
:
2185 auxNetDict
[sce_vnf
['uuid']] = {}
2186 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = task_id
2187 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':task_id
})
2188 net
["created"] = True
2191 #print "auxNetDict:"
2192 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2194 # 3. Creating new vm instances in the VIM
2195 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2196 sce_vnf_list
= sorted(scenarioDict
['vnfs'], key
=lambda k
: k
['name'])
2197 #for sce_vnf in scenarioDict['vnfs']:
2198 for sce_vnf
in sce_vnf_list
:
2199 if sce_vnf
.get("datacenter"):
2200 vim
= myvims
[ sce_vnf
["datacenter"] ]
2201 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"] ]
2202 datacenter_id
= sce_vnf
["datacenter"]
2204 vim
= myvims
[ default_datacenter_id
]
2205 myvim_thread_id
= myvim_threads_id
[ default_datacenter_id
]
2206 datacenter_id
= default_datacenter_id
2207 sce_vnf
["datacenter_id"] = datacenter_id
2209 for vm
in sce_vnf
['vms']:
2212 myVMDict
['name'] = "{}.{}.{}".format(instance_name
,sce_vnf
['name'],chr(96+i
))
2213 myVMDict
['description'] = myVMDict
['name'][0:99]
2215 # myVMDict['start'] = "no"
2216 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2217 #create image at vim in case it not exist
2218 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2219 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2220 vm
['vim_image_id'] = image_id
2222 #create flavor at vim in case it not exist
2223 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2224 if flavor_dict
['extended']!=None:
2225 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2226 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
2228 #Obtain information for additional disks
2229 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
2230 if not extended_flavor_dict
:
2231 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
2234 #extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
2235 myVMDict
['disks'] = None
2236 extended_info
= extended_flavor_dict
[0]['extended']
2237 if extended_info
!= None:
2238 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
2239 if 'disks' in extended_flavor_dict_yaml
:
2240 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
2242 vm
['vim_flavor_id'] = flavor_id
2243 myVMDict
['imageRef'] = vm
['vim_image_id']
2244 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2245 myVMDict
['networks'] = []
2247 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
2248 for iface
in vm
['interfaces']:
2250 if iface
['type']=="data":
2251 netDict
['type'] = iface
['model']
2252 elif "model" in iface
and iface
["model"]!=None:
2253 netDict
['model']=iface
['model']
2254 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2255 #discover type of interface looking at flavor
2256 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2257 for flavor_iface
in numa
.get('interfaces',[]):
2258 if flavor_iface
.get('name') == iface
['internal_name']:
2259 if flavor_iface
['dedicated'] == 'yes':
2260 netDict
['type']="PF" #passthrough
2261 elif flavor_iface
['dedicated'] == 'no':
2262 netDict
['type']="VF" #siov
2263 elif flavor_iface
['dedicated'] == 'yes:sriov':
2264 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2265 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2267 netDict
["use"]=iface
['type']
2268 if netDict
["use"]=="data" and not netDict
.get("type"):
2269 #print "netDict", netDict
2270 #print "iface", iface
2271 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'])
2272 if flavor_dict
.get('extended')==None:
2273 raise NfvoException(e_text
+ "After database migration some information is not available. \
2274 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2276 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2277 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2278 netDict
["type"]="virtual"
2279 if "vpci" in iface
and iface
["vpci"] is not None:
2280 netDict
['vpci'] = iface
['vpci']
2281 if "mac" in iface
and iface
["mac"] is not None:
2282 netDict
['mac_address'] = iface
['mac']
2283 if "port-security" in iface
and iface
["port-security"] is not None:
2284 netDict
['port_security'] = iface
['port-security']
2285 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2286 netDict
['floating_ip'] = iface
['floating-ip']
2287 netDict
['name'] = iface
['internal_name']
2288 if iface
['net_id'] is None:
2289 for vnf_iface
in sce_vnf
["interfaces"]:
2292 if vnf_iface
['interface_id']==iface
['uuid']:
2293 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
2296 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2297 if netDict
.get('net_id') and is_task_id(netDict
['net_id']):
2298 task_depends
[netDict
['net_id']] = instance_tasks
[netDict
['net_id']]
2299 #skip bridge ifaces not connected to any net
2300 #if 'net_id' not in netDict or netDict['net_id']==None:
2302 myVMDict
['networks'].append(netDict
)
2303 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2304 #print myVMDict['name']
2305 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2306 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2307 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2308 if vm
.get("boot_data"):
2309 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
2311 cloud_config_vm
= cloud_config
2312 task
= new_task("new-vm", (myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2313 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2314 cloud_config_vm
, myVMDict
['disks']), depends
=task_depends
)
2315 instance_tasks
[task
["id"]] = task
2316 tasks_to_launch
[myvim_thread_id
].append(task
)
2318 vm
['vim_id'] = vm_id
2319 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2320 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2321 for net
in myVMDict
['networks']:
2323 for iface
in vm
['interfaces']:
2324 if net
["name"]==iface
["internal_name"]:
2325 iface
["vim_id"]=net
["vim_id"]
2327 scenarioDict
["datacenter2tenant"] = myvim_threads_id
2328 logger
.debug("create_instance Deployment done scenarioDict: %s",
2329 yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False) )
2330 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
2331 for myvim_thread_id
,task_list
in tasks_to_launch
.items():
2332 for task
in task_list
:
2333 vim_threads
["running"][myvim_thread_id
].insert_task(task
)
2335 global_instance_tasks
[instance_id
] = instance_tasks
2336 # Update database with those ended instance_tasks
2337 # for task in instance_tasks.values():
2338 # if task["status"] == "ok":
2339 # if task["name"] == "new-vm":
2340 # mydb.update_rows("instance_vms", UPDATE={"vim_vm_id": task["result"]},
2341 # WHERE={"vim_vm_id": task["id"]})
2342 # elif task["name"] == "new-net":
2343 # mydb.update_rows("instance_nets", UPDATE={"vim_net_id": task["result"]},
2344 # WHERE={"vim_net_id": task["id"]})
2345 return mydb
.get_instance_scenario(instance_id
)
2346 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2347 message
= rollback(mydb
, myvims
, rollbackList
)
2348 if isinstance(e
, db_base_Exception
):
2349 error_text
= "database Exception"
2350 elif isinstance(e
, vimconn
.vimconnException
):
2351 error_text
= "VIM Exception"
2353 error_text
= "Exception"
2354 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2355 #logger.error("create_instance: %s", error_text)
2356 raise NfvoException(error_text
, e
.http_code
)
2359 def delete_instance(mydb
, tenant_id
, instance_id
):
2360 #print "Checking that the instance_id exists and getting the instance dictionary"
2361 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2362 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2363 tenant_id
= instanceDict
["tenant_id"]
2364 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2366 #1. Delete from Database
2367 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2376 for sce_vnf
in instanceDict
['vnfs']:
2377 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2378 if datacenter_key
not in myvims
:
2380 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2381 except NfvoException
as e
:
2382 logger
.error(str(e
))
2384 myvim_threads
[datacenter_key
] = myvim_thread
2385 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2386 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2388 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2389 sce_vnf
["datacenter_tenant_id"]))
2390 myvims
[datacenter_key
] = None
2392 myvims
[datacenter_key
] = vims
.values()[0]
2393 myvim
= myvims
[datacenter_key
]
2394 myvim_thread
= myvim_threads
[datacenter_key
]
2395 for vm
in sce_vnf
['vms']:
2397 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2401 if is_task_id(vm
['vim_vm_id']):
2402 task_id
= vm
['vim_vm_id']
2403 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2405 error_msg
+= "\n VM was scheduled for create, but task {} is not found".format(task_id
)
2408 if old_task
["status"] == "enqueued":
2409 old_task
["status"] = "deleted"
2410 elif old_task
["status"] == "error":
2412 elif old_task
["status"] == "processing":
2413 task
= new_task("del-vm", (task_id
, vm
["interfaces"]), depends
={task_id
: old_task
})
2415 task
= new_task("del-vm", (old_task
["result"], vm
["interfaces"]))
2417 task
= new_task("del-vm", (vm
['vim_vm_id'], vm
["interfaces"]) )
2419 myvim_thread
.insert_task(task
)
2420 except vimconn
.vimconnNotFoundException
as e
:
2421 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2422 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2423 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2424 except vimconn
.vimconnException
as e
:
2425 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2426 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2427 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2431 for net
in instanceDict
['nets']:
2432 if not net
['created']:
2433 continue #skip not created nets
2434 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2435 if datacenter_key
not in myvims
:
2437 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2438 except NfvoException
as e
:
2439 logger
.error(str(e
))
2441 myvim_threads
[datacenter_key
] = myvim_thread
2442 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2443 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2445 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2446 myvims
[datacenter_key
] = None
2448 myvims
[datacenter_key
] = vims
.values()[0]
2449 myvim
= myvims
[datacenter_key
]
2450 myvim_thread
= myvim_threads
[datacenter_key
]
2453 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2457 if is_task_id(net
['vim_net_id']):
2458 task_id
= net
['vim_net_id']
2459 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2461 error_msg
+= "\n NET was scheduled for create, but task {} is not found".format(task_id
)
2464 if old_task
["status"] == "enqueued":
2465 old_task
["status"] = "deleted"
2466 elif old_task
["status"] == "error":
2468 elif old_task
["status"] == "processing":
2469 task
= new_task("del-net", task_id
, depends
={task_id
: old_task
})
2471 task
= new_task("del-net", old_task
["result"])
2473 task
= new_task("del-net", (net
['vim_net_id'], net
['sdn_net_id']))
2475 myvim_thread
.insert_task(task
)
2476 except vimconn
.vimconnNotFoundException
as e
:
2477 error_msg
+= "\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2478 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2479 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2480 except vimconn
.vimconnException
as e
:
2481 error_msg
+= "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'],
2482 net
["datacenter_id"],
2483 e
.http_code
, str(e
))
2484 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2485 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2486 if len(error_msg
) > 0:
2487 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2489 return 'instance ' + message
+ ' deleted'
2492 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2493 '''Refreshes a scenario instance. It modifies instanceDict'''
2495 - 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
2498 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2499 # #print "nfvo.refresh_instance begins"
2500 # #print json.dumps(instanceDict, indent=4)
2502 # #print "Getting the VIM URL and the VIM tenant_id"
2505 # # 1. Getting VIM vm and net list
2506 # vms_updated = [] #List of VM instance uuids in openmano that were updated
2509 # for sce_vnf in instanceDict['vnfs']:
2510 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
2511 # if datacenter_key not in vm_list:
2512 # vm_list[datacenter_key] = []
2513 # if datacenter_key not in myvims:
2514 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
2515 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
2516 # if len(vims) == 0:
2517 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
2518 # myvims[datacenter_key] = None
2520 # myvims[datacenter_key] = vims.values()[0]
2521 # for vm in sce_vnf['vms']:
2522 # vm_list[datacenter_key].append(vm['vim_vm_id'])
2523 # vms_notupdated.append(vm["uuid"])
2525 # nets_updated = [] #List of VM instance uuids in openmano that were updated
2526 # nets_notupdated=[]
2528 # for net in instanceDict['nets']:
2529 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
2530 # if datacenter_key not in net_list:
2531 # net_list[datacenter_key] = []
2532 # if datacenter_key not in myvims:
2533 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
2534 # datacenter_tenant_id=net["datacenter_tenant_id"])
2535 # if len(vims) == 0:
2536 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
2537 # myvims[datacenter_key] = None
2539 # myvims[datacenter_key] = vims.values()[0]
2541 # net_list[datacenter_key].append(net['vim_net_id'])
2542 # nets_notupdated.append(net["uuid"])
2544 # # 1. Getting the status of all VMs
2546 # for datacenter_key in myvims:
2547 # if not vm_list.get(datacenter_key):
2551 # if not myvims[datacenter_key]:
2552 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2555 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
2557 # except vimconn.vimconnException as e:
2558 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2559 # failed_message = str(e)
2561 # for vm in vm_list[datacenter_key]:
2562 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2564 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2565 # for sce_vnf in instanceDict['vnfs']:
2566 # for vm in sce_vnf['vms']:
2567 # vm_id = vm['vim_vm_id']
2568 # interfaces = vm_dict[vm_id].pop('interfaces', [])
2569 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2570 # has_mgmt_iface = False
2571 # for iface in vm["interfaces"]:
2572 # if iface["type"]=="mgmt":
2573 # has_mgmt_iface = True
2574 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
2575 # vm_dict[vm_id]['status'] = "ACTIVE"
2576 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
2577 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
2578 # 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'):
2579 # vm['status'] = vm_dict[vm_id]['status']
2580 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
2581 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
2582 # # 2.1. Update in openmano DB the VMs whose status changed
2584 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
2585 # vms_notupdated.remove(vm["uuid"])
2587 # vms_updated.append(vm["uuid"])
2588 # except db_base_Exception as e:
2589 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2590 # # 2.2. Update in openmano DB the interface VMs
2591 # for interface in interfaces:
2592 # #translate from vim_net_id to instance_net_id
2593 # network_id_list=[]
2594 # for net in instanceDict['nets']:
2595 # if net["vim_net_id"] == interface["vim_net_id"]:
2596 # network_id_list.append(net["uuid"])
2597 # if not network_id_list:
2599 # del interface["vim_net_id"]
2601 # for network_id in network_id_list:
2602 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
2603 # except db_base_Exception as e:
2604 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
2606 # # 3. Getting the status of all nets
2608 # for datacenter_key in myvims:
2609 # if not net_list.get(datacenter_key):
2612 # failed_message = ""
2613 # if not myvims[datacenter_key]:
2614 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2617 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
2619 # except vimconn.vimconnException as e:
2620 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2621 # failed_message = str(e)
2623 # for net in net_list[datacenter_key]:
2624 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2626 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2627 # # TODO: update nets inside a vnf
2628 # for net in instanceDict['nets']:
2629 # net_id = net['vim_net_id']
2630 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
2631 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
2632 # 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'):
2633 # net['status'] = net_dict[net_id]['status']
2634 # net['error_msg'] = net_dict[net_id].get('error_msg')
2635 # net['vim_info'] = net_dict[net_id].get('vim_info')
2636 # # 5.1. Update in openmano DB the nets whose status changed
2638 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
2639 # nets_notupdated.remove(net["uuid"])
2641 # nets_updated.append(net["uuid"])
2642 # except db_base_Exception as e:
2643 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2645 # # Returns appropriate output
2646 # #print "nfvo.refresh_instance finishes"
2647 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2648 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
2649 instance_id
= instanceDict
['uuid']
2650 # if len(vms_notupdated)+len(nets_notupdated)>0:
2651 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
2652 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
2654 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2657 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2658 #print "Checking that the instance_id exists and getting the instance dictionary"
2659 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2660 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2662 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2663 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2665 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2666 myvim
= vims
.values()[0]
2669 input_vnfs
= action_dict
.pop("vnfs", [])
2670 input_vms
= action_dict
.pop("vms", [])
2671 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2675 for sce_vnf
in instanceDict
['vnfs']:
2676 for vm
in sce_vnf
['vms']:
2677 if not action_over_all
:
2678 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2679 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2682 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2683 if "console" in action_dict
:
2684 if not global_config
["http_console_proxy"]:
2685 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2686 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2687 protocol
=data
["protocol"],
2688 ip
= data
["server"],
2689 port
= data
["port"],
2690 suffix
= data
["suffix"]),
2694 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2695 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2696 "description": "this console is only reachable by local interface",
2701 #print "console data", data
2703 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2704 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2705 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2706 protocol
=data
["protocol"],
2707 ip
= global_config
["http_console_host"],
2708 port
= console_thread
.port
,
2709 suffix
= data
["suffix"]),
2713 except NfvoException
as e
:
2714 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2718 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2720 except vimconn
.vimconnException
as e
:
2721 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2724 if vm_ok
==0: #all goes wrong
2730 def create_or_use_console_proxy_thread(console_server
, console_port
):
2731 #look for a non-used port
2732 console_thread_key
= console_server
+ ":" + str(console_port
)
2733 if console_thread_key
in global_config
["console_thread"]:
2734 #global_config["console_thread"][console_thread_key].start_timeout()
2735 return global_config
["console_thread"][console_thread_key
]
2737 for port
in global_config
["console_port_iterator"]():
2738 #print "create_or_use_console_proxy_thread() port:", port
2739 if port
in global_config
["console_ports"]:
2742 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2744 global_config
["console_thread"][console_thread_key
] = clithread
2745 global_config
["console_ports"][port
] = console_thread_key
2747 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2748 #port used, try with onoher
2750 except cli
.ConsoleProxyException
as e
:
2751 raise NfvoException(str(e
), HTTP_Bad_Request
)
2752 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2755 def check_tenant(mydb
, tenant_id
):
2756 '''check that tenant exists at database'''
2757 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2759 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2763 def new_tenant(mydb
, tenant_dict
):
2764 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2768 def delete_tenant(mydb
, tenant
):
2769 #get nfvo_tenant info
2771 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2772 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2773 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2776 def new_datacenter(mydb
, datacenter_descriptor
):
2777 if "config" in datacenter_descriptor
:
2778 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2779 #Check that datacenter-type is correct
2780 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2783 module
= "vimconn_" + datacenter_type
2784 pkg
= __import__("osm_ro." + module
)
2785 vim_conn
= getattr(pkg
, module
)
2786 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
2787 except (IOError, ImportError):
2788 # if module_info and module_info[0]:
2789 # file.close(module_info[0])
2790 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2792 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2793 return datacenter_id
2796 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2797 # obtain data, check that only one exist
2798 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2801 datacenter_id
= datacenter
['uuid']
2802 where
={'uuid': datacenter
['uuid']}
2803 remove_port_mapping
= False
2804 if "config" in datacenter_descriptor
:
2805 if datacenter_descriptor
['config'] != None:
2807 new_config_dict
= datacenter_descriptor
["config"]
2810 for k
in new_config_dict
:
2811 if new_config_dict
[k
] == None:
2813 if k
== 'sdn-controller':
2814 remove_port_mapping
= True
2816 config_text
= datacenter
.get("config")
2819 config_dict
= yaml
.load(config_text
)
2820 config_dict
.update(new_config_dict
)
2824 except Exception as e
:
2825 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2827 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
2829 datacenter_descriptor
["config"] = None
2830 if remove_port_mapping
:
2832 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
2833 except ovimException
as e
:
2834 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
2836 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2837 return datacenter_id
2840 def delete_datacenter(mydb
, datacenter
):
2841 #get nfvo_tenant info
2842 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2843 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2845 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
2846 except ovimException
as e
:
2847 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
2848 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2851 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):
2852 #get datacenter info
2853 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
, vim_passwd
=vim_password
)
2854 datacenter_name
= myvim
["name"]
2856 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
2858 # get nfvo_tenant info
2859 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2860 if vim_tenant_name
==None:
2861 vim_tenant_name
=tenant_dict
['name']
2863 #check that this association does not exist before
2864 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2865 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2866 if len(tenants_datacenters
)>0:
2867 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2869 vim_tenant_id_exist_atdb
=False
2870 if not create_vim_tenant
:
2871 where_
={"datacenter_id": datacenter_id
}
2872 if vim_tenant_id
!=None:
2873 where_
["vim_tenant_id"] = vim_tenant_id
2874 if vim_tenant_name
!=None:
2875 where_
["vim_tenant_name"] = vim_tenant_name
2876 #check if vim_tenant_id is already at database
2877 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2878 if len(datacenter_tenants_dict
)>=1:
2879 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2880 vim_tenant_id_exist_atdb
=True
2881 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2883 datacenter_tenants_dict
= {}
2884 #insert at table datacenter_tenants
2885 else: #if vim_tenant_id==None:
2886 #create tenant at VIM if not provided
2888 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2889 except vimconn
.vimconnException
as e
:
2890 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2891 datacenter_tenants_dict
= {}
2892 datacenter_tenants_dict
["created"]="true"
2894 #fill datacenter_tenants table
2895 if not vim_tenant_id_exist_atdb
:
2896 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2897 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2898 datacenter_tenants_dict
["user"] = vim_username
2899 datacenter_tenants_dict
["passwd"] = vim_password
2900 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2902 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
2903 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2904 datacenter_tenants_dict
["uuid"] = id_
2906 #fill tenants_datacenters table
2907 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
2908 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
2909 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2911 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
2912 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
2913 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
2914 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
2916 thread_id
= datacenter_tenants_dict
["uuid"]
2917 vim_threads
["running"][thread_id
] = new_thread
2918 return datacenter_id
2921 def edit_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=None, vim_tenant_name
=None,
2922 vim_username
=None, vim_password
=None, config
=None):
2923 #Obtain the data of this datacenter_tenant_id
2924 vim_data
= mydb
.get_rows(
2925 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
2926 "datacenter_tenants.passwd", "datacenter_tenants.config"),
2927 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
2928 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
2929 "tenants_datacenters.datacenter_id": datacenter_id
})
2931 logger
.debug(str(vim_data
))
2932 if len(vim_data
) < 1:
2933 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
2937 v
['config'] = yaml
.load(v
['config'])
2940 v
['vim_tenant_id'] = vim_tenant_id
2942 v
['vim_tenant_name'] = vim_tenant_name
2944 v
['user'] = vim_username
2946 v
['passwd'] = vim_password
2950 v
['config'].update(config
)
2952 logger
.debug(str(v
))
2953 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
2954 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
2955 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
2957 return datacenter_id
2959 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2960 #get datacenter info
2961 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2963 #get nfvo_tenant info
2964 if not tenant_id
or tenant_id
=="any":
2967 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2968 tenant_uuid
= tenant_dict
['uuid']
2970 #check that this association exist before
2971 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2973 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2974 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2975 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2976 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2978 #delete this association
2979 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2981 #get vim_tenant info and deletes
2983 for tenant_datacenter_item
in tenant_datacenter_list
:
2984 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2985 #try to delete vim:tenant
2987 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2988 if vim_tenant_dict
['created']=='true':
2989 #delete tenant at VIM if created by NFVO
2991 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2992 except vimconn
.vimconnException
as e
:
2993 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2994 logger
.warn(warning
)
2995 except db_base_Exception
as e
:
2996 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2997 pass # the error will be caused because dependencies, vim_tenant can not be deleted
2998 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
2999 thread
= vim_threads
["running"][thread_id
]
3000 thread
.insert_task(new_task("exit", None))
3001 vim_threads
["deleting"][thread_id
] = thread
3002 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
3005 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
3007 #get datacenter info
3008 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3010 if 'net-update' in action_dict
:
3012 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
3014 except vimconn
.vimconnException
as e
:
3015 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
3016 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3017 #update nets Change from VIM format to NFVO format
3020 net_nfvo
={'datacenter_id': datacenter_id
}
3021 net_nfvo
['name'] = net
['name']
3022 #net_nfvo['description']= net['name']
3023 net_nfvo
['vim_net_id'] = net
['id']
3024 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3025 net_nfvo
['shared'] = net
['shared']
3026 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3027 net_list
.append(net_nfvo
)
3028 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
3029 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
3031 elif 'net-edit' in action_dict
:
3032 net
= action_dict
['net-edit'].pop('net')
3033 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3034 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
3035 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3037 elif 'net-delete' in action_dict
:
3038 net
= action_dict
['net-deelte'].get('net')
3039 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3040 result
= mydb
.delete_row(FROM
='datacenter_nets',
3041 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3045 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
3048 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
3049 #get datacenter info
3050 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3052 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
3053 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
3054 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
3058 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
3059 #get datacenter info
3060 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3063 action_dict
= action_dict
["netmap"]
3064 if 'vim_id' in action_dict
:
3065 filter_dict
["id"] = action_dict
['vim_id']
3066 if 'vim_name' in action_dict
:
3067 filter_dict
["name"] = action_dict
['vim_name']
3069 filter_dict
["shared"] = True
3072 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
3073 except vimconn
.vimconnException
as e
:
3074 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
3075 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3076 if len(vim_nets
)>1 and action_dict
:
3077 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
3078 elif len(vim_nets
)==0: # and action_dict:
3079 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
3081 for net
in vim_nets
:
3082 net_nfvo
={'datacenter_id': datacenter_id
}
3083 if action_dict
and "name" in action_dict
:
3084 net_nfvo
['name'] = action_dict
['name']
3086 net_nfvo
['name'] = net
['name']
3087 #net_nfvo['description']= net['name']
3088 net_nfvo
['vim_net_id'] = net
['id']
3089 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3090 net_nfvo
['shared'] = net
['shared']
3091 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3093 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
3094 net_nfvo
["status"] = "OK"
3095 net_nfvo
["uuid"] = net_id
3096 except db_base_Exception
as e
:
3100 net_nfvo
["status"] = "FAIL: " + str(e
)
3101 net_list
.append(net_nfvo
)
3104 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
3105 # obtain all network data
3107 if utils
.check_valid_uuid(network_id
):
3108 filter_dict
= {"id": network_id
}
3110 filter_dict
= {"name": network_id
}
3112 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3113 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
3114 except vimconn
.vimconnException
as e
:
3115 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
3116 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
3118 # ensure the network is defined
3119 if len(network
) == 0:
3120 raise NfvoException("Network {} is not present in the system".format(network_id
),
3123 # ensure there is only one network with the provided name
3124 if len(network
) > 1:
3125 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), HTTP_Bad_Request
)
3127 # ensure it is a dataplane network
3128 if network
[0]['type'] != 'data':
3131 # ensure we use the id
3132 network_id
= network
[0]['id']
3134 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
3135 # and with instance_scenario_id==NULL
3136 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
3137 search_dict
= {'vim_net_id': network_id
}
3140 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
3141 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
3142 except db_base_Exception
as e
:
3143 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
3144 network_id
) + str(e
), HTTP_Internal_Server_Error
)
3148 if net
['sdn_net_id'] != None:
3150 sdn_net_id
= net
['sdn_net_id']
3152 if sdn_net_counter
== 0:
3154 elif sdn_net_counter
== 1:
3157 raise NfvoException("More than one SDN network is associated to vim network {}".format(
3158 network_id
), HTTP_Internal_Server_Error
)
3160 def get_sdn_controller_id(mydb
, datacenter
):
3161 # Obtain sdn controller id
3162 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
3166 return yaml
.load(config
).get('sdn-controller')
3168 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
3170 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
3171 if not sdn_network_id
:
3172 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), HTTP_Internal_Server_Error
)
3174 #Obtain sdn controller id
3175 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
3176 if not controller_id
:
3177 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), HTTP_Internal_Server_Error
)
3179 #Obtain sdn controller info
3180 sdn_controller
= ovim
.show_of_controller(controller_id
)
3183 'name': 'external_port',
3184 'net_id': sdn_network_id
,
3185 'ofc_id': controller_id
,
3186 'switch_dpid': sdn_controller
['dpid'],
3187 'switch_port': descriptor
['port']
3190 if 'vlan' in descriptor
:
3191 port_data
['vlan'] = descriptor
['vlan']
3192 if 'mac' in descriptor
:
3193 port_data
['mac'] = descriptor
['mac']
3195 result
= ovim
.new_port(port_data
)
3196 except ovimException
as e
:
3197 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
3198 sdn_network_id
, network_id
) + str(e
), HTTP_Internal_Server_Error
)
3199 except db_base_Exception
as e
:
3200 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
3201 network_id
) + str(e
), HTTP_Internal_Server_Error
)
3203 return 'Port uuid: '+ result
3205 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
3207 filter = {'uuid': port_id
}
3209 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
3210 if not sdn_network_id
:
3211 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
3212 HTTP_Internal_Server_Error
)
3213 #in case no port_id is specified only ports marked as 'external_port' will be detached
3214 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
3217 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
3218 except ovimException
as e
:
3219 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
3220 HTTP_Internal_Server_Error
)
3222 if len(port_list
) == 0:
3223 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
3227 for port
in port_list
:
3229 port_uuid_list
.append(port
['uuid'])
3230 ovim
.delete_port(port
['uuid'])
3231 except ovimException
as e
:
3232 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), HTTP_Internal_Server_Error
)
3234 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
3236 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
3237 #get datacenter info
3238 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3241 if utils
.check_valid_uuid(name
):
3242 filter_dict
["id"] = name
3244 filter_dict
["name"] = name
3246 if item
=="networks":
3247 #filter_dict['tenant_id'] = myvim['tenant_id']
3248 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
3250 if len(content
) == 0:
3251 raise NfvoException("Network {} is not present in the system. ".format(name
),
3254 #Update the networks with the attached ports
3256 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
3257 if sdn_network_id
!= None:
3259 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
3260 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
3261 except ovimException
as e
:
3262 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), HTTP_Internal_Server_Error
)
3263 #Remove field name and if port name is external_port save it as 'type'
3264 for port
in port_list
:
3265 if port
['name'] == 'external_port':
3266 port
['type'] = "External"
3268 net
['sdn_network_id'] = sdn_network_id
3269 net
['sdn_attached_ports'] = port_list
3271 elif item
=="tenants":
3272 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
3273 elif item
== "images":
3275 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
3277 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3278 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
3279 if name
and len(content
)==1:
3280 return {item
[:-1]: content
[0]}
3281 elif name
and len(content
)==0:
3282 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
3285 return {item
: content
}
3286 except vimconn
.vimconnException
as e
:
3287 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
3288 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
3291 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
3292 #get datacenter info
3293 if tenant_id
== "any":
3296 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3298 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
3299 logger
.debug("vim_action_delete vim response: " + str(content
))
3300 items
= content
.values()[0]
3301 if type(items
)==list and len(items
)==0:
3302 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
3303 elif type(items
)==list and len(items
)>1:
3304 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
3305 else: # it is a dict
3306 item_id
= items
["id"]
3307 item_name
= str(items
.get("name"))
3310 if item
=="networks":
3311 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
3312 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
3313 if sdn_network_id
!= None:
3314 #Delete any port attachment to this network
3316 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
3317 except ovimException
as e
:
3318 raise NfvoException(
3319 "ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
3320 HTTP_Internal_Server_Error
)
3322 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
3323 for port
in port_list
:
3324 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
3326 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
3328 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id
, 'vim_net_id': item_id
})
3329 except db_base_Exception
as e
:
3330 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
3331 str(e
), HTTP_Internal_Server_Error
)
3333 #Delete the SDN network
3335 ovim
.delete_network(sdn_network_id
)
3336 except ovimException
as e
:
3337 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
3338 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
3339 HTTP_Internal_Server_Error
)
3341 content
= myvim
.delete_network(item_id
)
3342 elif item
=="tenants":
3343 content
= myvim
.delete_tenant(item_id
)
3344 elif item
== "images":
3345 content
= myvim
.delete_image(item_id
)
3347 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3348 except vimconn
.vimconnException
as e
:
3349 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
3350 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
3352 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
3355 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
3356 #get datacenter info
3357 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
3358 if tenant_id
== "any":
3360 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3362 if item
=="networks":
3363 net
= descriptor
["network"]
3364 net_name
= net
.pop("name")
3365 net_type
= net
.pop("type", "bridge")
3366 net_public
= net
.pop("shared", False)
3367 net_ipprofile
= net
.pop("ip_profile", None)
3368 net_vlan
= net
.pop("vlan", None)
3369 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
3371 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
3372 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
3375 sdn_network
['vlan'] = net_vlan
3376 sdn_network
['type'] = net_type
3377 sdn_network
['name'] = net_name
3378 ovim_content
= ovim
.new_network(sdn_network
)
3379 except ovimException
as e
:
3380 self
.logger
.error("ovimException creating SDN network={} ".format(
3381 sdn_network
) + str(e
), exc_info
=True)
3382 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
3383 HTTP_Internal_Server_Error
)
3385 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
3386 # use instance_scenario_id=None to distinguish from real instaces of nets
3387 correspondence
= {'instance_scenario_id': None, 'sdn_net_id': ovim_content
, 'vim_net_id': content
}
3388 #obtain datacenter_tenant_id
3389 correspondence
['datacenter_tenant_id'] = mydb
.get_rows(SELECT
=('uuid',), FROM
='datacenter_tenants', WHERE
={'datacenter_id': datacenter
})[0]['uuid']
3392 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
3393 except db_base_Exception
as e
:
3394 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
3395 str(e
), HTTP_Internal_Server_Error
)
3396 elif item
=="tenants":
3397 tenant
= descriptor
["tenant"]
3398 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
3400 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3401 except vimconn
.vimconnException
as e
:
3402 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
3404 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
3406 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
3407 data
= ovim
.new_of_controller(sdn_controller
)
3408 logger
.debug('New SDN controller created with uuid {}'.format(data
))
3411 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
3412 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
3413 msg
= 'SDN controller {} updated'.format(data
)
3417 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
3418 if controller_id
== None:
3419 data
= ovim
.get_of_controllers()
3421 data
= ovim
.show_of_controller(controller_id
)
3423 msg
= 'SDN controller list:\n {}'.format(data
)
3427 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
3428 select_
= ('uuid', 'config')
3429 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
3430 for datacenter
in datacenters
:
3431 if datacenter
['config']:
3432 config
= yaml
.load(datacenter
['config'])
3433 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
3434 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
3436 data
= ovim
.delete_of_controller(controller_id
)
3437 msg
= 'SDN controller {} deleted'.format(data
)
3441 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
3442 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
3443 if len(controller
) < 1:
3444 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
3447 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
3449 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
3451 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
3452 switch_dpid
= sdn_controller
["dpid"]
3455 for compute_node
in sdn_port_mapping
:
3456 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
3458 element
["compute_node"] = compute_node
["compute_node"]
3459 for port
in compute_node
["ports"]:
3460 element
["pci"] = port
.get("pci")
3461 element
["switch_port"] = port
.get("switch_port")
3462 element
["switch_mac"] = port
.get("switch_mac")
3463 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
3464 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
3465 " or 'switch_mac'", HTTP_Bad_Request
)
3466 maps
.append(dict(element
))
3468 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
3470 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
3471 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
3474 "sdn-controller": None,
3475 "datacenter-id": datacenter_id
,
3477 "ports_mapping": list()
3480 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
3481 if datacenter
['config']:
3482 config
= yaml
.load(datacenter
['config'])
3483 if 'sdn-controller' in config
:
3484 controller_id
= config
['sdn-controller']
3485 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
3486 result
["sdn-controller"] = controller_id
3487 result
["dpid"] = sdn_controller
["dpid"]
3489 if result
["sdn-controller"] == None:
3490 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), HTTP_Bad_Request
)
3491 if result
["dpid"] == None:
3492 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
3493 HTTP_Internal_Server_Error
)
3498 ports_correspondence_dict
= dict()
3500 if result
["sdn-controller"] != link
["ofc_id"]:
3501 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
3502 if result
["dpid"] != link
["switch_dpid"]:
3503 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
3505 element
["pci"] = link
["pci"]
3506 if link
["switch_port"]:
3507 element
["switch_port"] = link
["switch_port"]
3508 if link
["switch_mac"]:
3509 element
["switch_mac"] = link
["switch_mac"]
3511 if not link
["compute_node"] in ports_correspondence_dict
:
3513 content
["compute_node"] = link
["compute_node"]
3514 content
["ports"] = list()
3515 ports_correspondence_dict
[link
["compute_node"]] = content
3517 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
3519 for key
in sorted(ports_correspondence_dict
):
3520 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
3524 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
3525 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})