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