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 uuid
import uuid4
42 from db_base
import db_base_Exception
45 from threading
import Lock
47 from lib_osm_openvim
import ovim
as ovim_module
48 from lib_osm_openvim
.ovim
import ovimException
51 global vimconn_imported
53 global default_volume_size
54 default_volume_size
= '5' #size in GB
59 vimconn_imported
= {} # dictionary with VIM type as key, loaded module as value
60 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
61 vim_persistent_info
= {}
62 logger
= logging
.getLogger('openmano.nfvo')
64 global_instance_tasks
= {}
69 class NfvoException(Exception):
70 def __init__(self
, message
, http_code
):
71 self
.http_code
= http_code
72 Exception.__init
__(self
, message
)
78 if task_id
<= last_task_id
:
79 task_id
= last_task_id
+ 0.000001
80 last_task_id
= task_id
81 return "TASK.{:.6f}".format(task_id
)
84 def new_task(name
, params
, depends
=None):
85 task_id
= get_task_id()
86 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
88 task
["depends"] = depends
93 return True if id[:5] == "TASK." else False
96 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
97 name
= datacenter_name
[:16]
98 if name
not in vim_threads
["names"]:
99 vim_threads
["names"].append(name
)
101 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
102 if name
not in vim_threads
["names"]:
103 vim_threads
["names"].append(name
)
105 name
= datacenter_id
+ "-" + tenant_id
106 vim_threads
["names"].append(name
)
110 def start_service(mydb
):
111 global db
, global_config
112 db
= nfvo_db
.nfvo_db()
113 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
116 # Initialize openvim for SDN control
117 # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
118 # TODO: review ovim.py to delete not needed configuration
119 ovim_configuration
= {
120 'logger_name': 'openmano.ovim',
121 'network_vlan_range_start': 1000,
122 'network_vlan_range_end': 4096,
123 'db_name': global_config
["db_ovim_name"],
124 'db_host': global_config
["db_ovim_host"],
125 'db_user': global_config
["db_ovim_user"],
126 'db_passwd': global_config
["db_ovim_passwd"],
129 'network_type': 'bridge',
130 #TODO: log_level_of should not be needed. To be modified in ovim
131 'log_level_of': 'DEBUG'
134 ovim
= ovim_module
.ovim(ovim_configuration
)
137 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\
138 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
139 select_
= ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin',
140 'd.name as datacenter_name', 'dt.uuid as datacenter_tenant_id',
141 'dt.vim_tenant_name as vim_tenant_name', 'dt.vim_tenant_id as vim_tenant_id',
142 'user', 'passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
143 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
145 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
146 'datacenter_id': vim
.get('datacenter_id')}
148 extra
.update(yaml
.load(vim
["config"]))
149 if vim
.get('dt_config'):
150 extra
.update(yaml
.load(vim
["dt_config"]))
151 if vim
["type"] not in vimconn_imported
:
154 module
= "vimconn_" + vim
["type"]
155 pkg
= __import__("osm_ro." + module
)
156 vim_conn
= getattr(pkg
, module
)
157 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
158 # vim_conn = imp.load_module(vim["type"], *module_info)
159 vimconn_imported
[vim
["type"]] = vim_conn
160 except (IOError, ImportError) as e
:
161 # if module_info and module_info[0]:
162 # file.close(module_info[0])
163 raise NfvoException("Unknown vim type '{}'. Cannot open file '{}.py'; {}: {}".format(
164 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
166 thread_id
= vim
['datacenter_tenant_id']
167 vim_persistent_info
[thread_id
] = {}
170 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
171 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
172 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
173 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
174 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
175 user
=vim
['user'], passwd
=vim
['passwd'],
176 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
178 except Exception as e
:
179 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, e
),
180 HTTP_Internal_Server_Error
)
181 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['vim_tenant_id'], vim
['vim_tenant_name'],
182 vim
['vim_tenant_id'])
183 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, vim
['datacenter_name'],
184 vim
['datacenter_tenant_id'], db
=db
, db_lock
=db_lock
, ovim
=ovim
)
186 vim_threads
["running"][thread_id
] = new_thread
187 except db_base_Exception
as e
:
188 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
189 except ovim_module
.ovimException
as e
:
191 if message
[:22] == "DATABASE wrong version":
192 message
= "DATABASE wrong version of lib_osm_openvim {msg} -d{dbname} -u{dbuser} -p{dbpass} {ver}' "\
193 "at host {dbhost}".format(
194 msg
=message
[22:-3], dbname
=global_config
["db_ovim_name"],
195 dbuser
=global_config
["db_ovim_user"], dbpass
=global_config
["db_ovim_passwd"],
196 ver
=message
[-3:-1], dbhost
=global_config
["db_ovim_host"])
197 raise NfvoException(message
, HTTP_Bad_Request
)
201 global ovim
, global_config
204 for thread_id
,thread
in vim_threads
["running"].items():
205 thread
.insert_task(new_task("exit", None))
206 vim_threads
["deleting"][thread_id
] = thread
207 vim_threads
["running"] = {}
208 if global_config
and global_config
.get("console_thread"):
209 for thread
in global_config
["console_thread"]:
210 thread
.terminate
= True
213 return ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config
["version"],
214 global_config
["version_date"] ))
217 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
219 return result, content:
220 <0, error_text upon error
221 nb_records, flavor_list on success
224 WHERE_dict
['vnf_id'] = vnf_id
225 if nfvo_tenant
is not None:
226 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
228 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
229 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
230 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
231 #print "get_flavor_list result:", result
232 #print "get_flavor_list content:", content
234 for flavor
in flavors
:
235 flavorList
.append(flavor
['flavor_id'])
239 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
241 return result, content:
242 <0, error_text upon error
243 nb_records, flavor_list on success
246 WHERE_dict
['vnf_id'] = vnf_id
247 if nfvo_tenant
is not None:
248 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
250 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
251 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
254 imageList
.append(image
['image_id'])
258 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
259 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
260 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
261 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
262 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
263 raise exception upon error
266 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
267 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
268 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
269 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
270 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
271 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
272 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
273 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'
274 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
275 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
276 'user','passwd', 'dt.config as dt_config')
278 from_
= 'datacenters as d'
279 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
281 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
284 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
285 'datacenter_id': vim
.get('datacenter_id')}
287 extra
.update(yaml
.load(vim
["config"]))
288 if vim
.get('dt_config'):
289 extra
.update(yaml
.load(vim
["dt_config"]))
290 if vim
["type"] not in vimconn_imported
:
293 module
= "vimconn_" + vim
["type"]
294 pkg
= __import__("osm_ro." + module
)
295 vim_conn
= getattr(pkg
, module
)
296 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
297 # vim_conn = imp.load_module(vim["type"], *module_info)
298 vimconn_imported
[vim
["type"]] = vim_conn
299 except (IOError, ImportError) as e
:
300 # if module_info and module_info[0]:
301 # file.close(module_info[0])
302 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
303 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
306 if 'datacenter_tenant_id' in vim
:
307 thread_id
= vim
["datacenter_tenant_id"]
308 if thread_id
not in vim_persistent_info
:
309 vim_persistent_info
[thread_id
] = {}
310 persistent_info
= vim_persistent_info
[thread_id
]
314 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
315 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
316 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
317 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
318 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
319 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
320 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
321 config
=extra
, persistent_info
=persistent_info
323 except Exception as e
:
324 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
326 except db_base_Exception
as e
:
327 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
330 def rollback(mydb
, vims
, rollback_list
):
332 #delete things by reverse order
333 for i
in range(len(rollback_list
)-1, -1, -1):
334 item
= rollback_list
[i
]
335 if item
["where"]=="vim":
336 if item
["vim_id"] not in vims
:
338 if is_task_id(item
["uuid"]):
340 vim
= vims
[item
["vim_id"]]
342 if item
["what"]=="image":
343 vim
.delete_image(item
["uuid"])
344 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
345 elif item
["what"]=="flavor":
346 vim
.delete_flavor(item
["uuid"])
347 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
348 elif item
["what"]=="network":
349 vim
.delete_network(item
["uuid"])
350 elif item
["what"]=="vm":
351 vim
.delete_vminstance(item
["uuid"])
352 except vimconn
.vimconnException
as e
:
353 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
354 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
355 except db_base_Exception
as e
:
356 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
360 if item
["what"]=="image":
361 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
362 elif item
["what"]=="flavor":
363 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
364 except db_base_Exception
as e
:
365 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
366 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
367 if len(undeleted_items
)==0:
368 return True," Rollback successful."
370 return False," Rollback fails to delete: " + str(undeleted_items
)
373 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
375 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
377 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
379 #dataplane interfaces
380 for numa
in vnfc
.get("numas",() ):
381 for interface
in numa
.get("interfaces",()):
382 if interface
["name"] in name_dict
:
384 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
385 vnfc
["name"], interface
["name"]),
387 name_dict
[ interface
["name"] ] = "underlay"
389 for interface
in vnfc
.get("bridge-ifaces",() ):
390 if interface
["name"] in name_dict
:
392 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
393 vnfc
["name"], interface
["name"]),
395 name_dict
[ interface
["name"] ] = "overlay"
396 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
397 # check bood-data info
398 # if "boot-data" in vnfc:
399 # # check that user-data is incompatible with users and config-files
400 # if (vnfc["boot-data"].get("users") or vnfc["boot-data"].get("config-files")) and vnfc["boot-data"].get("user-data"):
401 # raise NfvoException(
402 # "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
405 #check if the info in external_connections matches with the one in the vnfcs
407 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
408 if external_connection
["name"] in name_list
:
410 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
411 external_connection
["name"]),
413 name_list
.append(external_connection
["name"])
414 if external_connection
["VNFC"] not in vnfc_interfaces
:
416 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
417 external_connection
["name"], external_connection
["VNFC"]),
420 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
422 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
423 external_connection
["name"],
424 external_connection
["local_iface_name"]),
427 #check if the info in internal_connections matches with the one in the vnfcs
429 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
430 if internal_connection
["name"] in name_list
:
432 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
433 internal_connection
["name"]),
435 name_list
.append(internal_connection
["name"])
436 #We should check that internal-connections of type "ptp" have only 2 elements
438 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
440 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
441 internal_connection
["name"],
442 'ptp' if vnf_descriptor_version
==1 else 'e-line',
443 'data' if vnf_descriptor_version
==1 else "e-lan"),
445 for port
in internal_connection
["elements"]:
447 iface
= port
["local_iface_name"]
448 if vnf
not in vnfc_interfaces
:
450 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
451 internal_connection
["name"], vnf
),
453 if iface
not in vnfc_interfaces
[ vnf
]:
455 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
456 internal_connection
["name"], iface
),
458 return -HTTP_Bad_Request
,
459 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
460 if vnfc_interfaces
[vnf
][iface
] == "overlay":
461 internal_connection
["type"] = "bridge"
463 internal_connection
["type"] = "data"
464 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
465 if vnfc_interfaces
[vnf
][iface
] == "overlay":
466 internal_connection
["implementation"] = "overlay"
468 internal_connection
["implementation"] = "underlay"
469 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
470 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
472 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
473 internal_connection
["name"],
474 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
475 'data' if vnf_descriptor_version
==1 else 'underlay'),
477 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
478 vnfc_interfaces
[vnf
][iface
] == "underlay":
480 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
481 internal_connection
["name"], iface
,
482 'data' if vnf_descriptor_version
==1 else 'underlay',
483 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
487 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=None):
489 if only_create_at_vim
:
490 image_mano_id
= image_dict
['uuid']
491 if return_on_error
== None:
492 return_on_error
= True
494 if image_dict
['location']:
495 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
497 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
499 image_mano_id
= images
[0]['uuid']
501 #create image in MANO DB
502 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
503 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
504 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
506 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
507 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
508 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
509 #create image at every vim
510 for vim_id
,vim
in vims
.iteritems():
511 image_created
="false"
513 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
514 #look at VIM if this image exist
516 if image_dict
['location'] is not None:
517 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
520 filter_dict
['name'] = image_dict
['universal_name']
521 if image_dict
.get('checksum') != None:
522 filter_dict
['checksum'] = image_dict
['checksum']
523 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
524 vim_images
= vim
.get_image_list(filter_dict
)
525 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
526 if len(vim_images
) > 1:
527 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), HTTP_Conflict
)
528 elif len(vim_images
) == 0:
529 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
531 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
532 image_vim_id
= vim_images
[0]['id']
534 except vimconn
.vimconnNotFoundException
as e
:
535 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
537 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
538 if image_dict
['location']:
539 image_vim_id
= vim
.new_image(image_dict
)
540 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
543 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
544 raise vimconn
.vimconnException(str(e
))
545 except vimconn
.vimconnException
as e
:
547 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
550 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
552 except vimconn
.vimconnException
as e
:
554 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
556 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
559 #if we reach here, the image has been created or existed
561 #add new vim_id at datacenters_images
562 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
563 elif image_db
[0]["vim_id"]!=image_vim_id
:
564 #modify existing vim_id at datacenters_images
565 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
567 return image_vim_id
if only_create_at_vim
else image_mano_id
570 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
571 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
572 'ram':flavor_dict
.get('ram'),
573 'vcpus':flavor_dict
.get('vcpus'),
575 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
576 del flavor_dict
['extended']
577 if 'extended' in flavor_dict
:
578 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
580 #look if flavor exist
581 if only_create_at_vim
:
582 flavor_mano_id
= flavor_dict
['uuid']
583 if return_on_error
== None:
584 return_on_error
= True
586 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
588 flavor_mano_id
= flavors
[0]['uuid']
591 #create one by one the images of aditional disks
592 dev_image_list
=[] #list of images
593 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
595 for device
in flavor_dict
['extended'].get('devices',[]):
596 if "image" not in device
and "image name" not in device
:
599 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
600 image_dict
['universal_name']=device
.get('image name')
601 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
602 image_dict
['location']=device
.get('image')
603 #image_dict['new_location']=vnfc.get('image location')
604 image_dict
['checksum']=device
.get('image checksum')
605 image_metadata_dict
= device
.get('image metadata', None)
606 image_metadata_str
= None
607 if image_metadata_dict
!= None:
608 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
609 image_dict
['metadata']=image_metadata_str
610 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
611 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
612 dev_image_list
.append(image_id
)
614 temp_flavor_dict
['name'] = flavor_dict
['name']
615 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
616 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
617 flavor_mano_id
= content
618 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
619 #create flavor at every vim
620 if 'uuid' in flavor_dict
:
621 del flavor_dict
['uuid']
623 for vim_id
,vim
in vims
.items():
624 flavor_created
="false"
626 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
627 #look at VIM if this flavor exist SKIPPED
628 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
630 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
634 #Create the flavor in VIM
635 #Translate images at devices from MANO id to VIM id
637 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
638 #make a copy of original devices
641 for device
in flavor_dict
["extended"].get("devices",[]):
644 devices_original
.append(dev
)
645 if 'image' in device
:
647 if 'image metadata' in device
:
648 del device
['image metadata']
650 for index
in range(0,len(devices_original
)) :
651 device
=devices_original
[index
]
652 if "image" not in device
and "image name" not in device
:
654 disk_list
.append({'size': device
.get('size', default_volume_size
)})
657 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
658 image_dict
['universal_name']=device
.get('image name')
659 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
660 image_dict
['location']=device
.get('image')
661 #image_dict['new_location']=device.get('image location')
662 image_dict
['checksum']=device
.get('image checksum')
663 image_metadata_dict
= device
.get('image metadata', None)
664 image_metadata_str
= None
665 if image_metadata_dict
!= None:
666 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
667 image_dict
['metadata']=image_metadata_str
668 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
669 image_dict
["uuid"]=image_mano_id
670 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
672 #save disk information (image must be based on and size
673 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
675 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
678 #check that this vim_id exist in VIM, if not create
679 flavor_vim_id
=flavor_db
[0]["vim_id"]
681 vim
.get_flavor(flavor_vim_id
)
682 continue #flavor exist
683 except vimconn
.vimconnException
:
685 #create flavor at vim
686 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
689 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
690 flavor_create
="false"
691 except vimconn
.vimconnException
as e
:
694 if not flavor_vim_id
:
695 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
696 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
697 flavor_created
="true"
698 except vimconn
.vimconnException
as e
:
700 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
702 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
705 #if reach here the flavor has been create or exist
706 if len(flavor_db
)==0:
707 #add new vim_id at datacenters_flavors
708 extended_devices_yaml
= None
709 if len(disk_list
) > 0:
710 extended_devices
= dict()
711 extended_devices
['disks'] = disk_list
712 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
713 mydb
.new_row('datacenters_flavors',
714 {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
,
715 'created':flavor_created
,'extended': extended_devices_yaml
})
716 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
717 #modify existing vim_id at datacenters_flavors
718 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
720 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
723 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
726 # Step 1. Check the VNF descriptor
727 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
728 # Step 2. Check tenant exist
730 if tenant_id
!= "any":
731 check_tenant(mydb
, tenant_id
)
732 if "tenant_id" in vnf_descriptor
["vnf"]:
733 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
734 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
737 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
738 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
739 if global_config
["auto_push_VNF_to_VIMs"]:
740 vims
= get_vim(mydb
, tenant_id
)
742 # Step 4. Review the descriptor and add missing fields
743 #print vnf_descriptor
744 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
745 vnf_name
= vnf_descriptor
['vnf']['name']
746 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
747 if "physical" in vnf_descriptor
['vnf']:
748 del vnf_descriptor
['vnf']['physical']
749 #print vnf_descriptor
751 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
752 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
753 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
755 #For each VNFC, we add it to the VNFCDict and we create a flavor.
756 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
757 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
759 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
760 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
762 VNFCitem
["name"] = vnfc
['name']
763 VNFCitem
["availability_zone"] = vnfc
.get('availability_zone')
764 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
766 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
769 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
770 myflavorDict
["description"] = VNFCitem
["description"]
771 myflavorDict
["ram"] = vnfc
.get("ram", 0)
772 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
773 myflavorDict
["disk"] = vnfc
.get("disk", 1)
774 myflavorDict
["extended"] = {}
776 devices
= vnfc
.get("devices")
778 myflavorDict
["extended"]["devices"] = devices
781 # 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
782 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
784 # Previous code has been commented
785 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
786 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
787 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
788 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
790 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
792 # print "Error creating flavor: unknown processor model. Rollback successful."
793 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
795 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
796 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
798 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
799 myflavorDict
['extended']['numas'] = vnfc
['numas']
803 # Step 6.2 New flavors are created in the VIM
804 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
806 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
807 VNFCitem
["flavor_id"] = flavor_id
808 VNFCDict
[vnfc
['name']] = VNFCitem
810 logger
.debug("Creating new images in the VIM for each VNFC")
811 # Step 6.3 New images are created in the VIM
812 #For each VNFC, we must create the appropriate image.
813 #This "for" loop might be integrated with the previous one
814 #In case this integration is made, the VNFCDict might become a VNFClist.
815 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
816 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
818 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
819 image_dict
['universal_name']=vnfc
.get('image name')
820 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
821 image_dict
['location']=vnfc
.get('VNFC image')
822 #image_dict['new_location']=vnfc.get('image location')
823 image_dict
['checksum']=vnfc
.get('image checksum')
824 image_metadata_dict
= vnfc
.get('image metadata', None)
825 image_metadata_str
= None
826 if image_metadata_dict
is not None:
827 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
828 image_dict
['metadata']=image_metadata_str
829 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
830 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
831 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
832 VNFCDict
[vnfc
['name']]["image_id"] = image_id
833 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
834 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
835 if vnfc
.get("boot-data"):
836 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
839 # Step 7. Storing the VNF descriptor in the repository
840 if "descriptor" not in vnf_descriptor
["vnf"]:
841 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
843 # Step 8. Adding the VNF to the NFVO DB
844 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
846 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
847 _
, message
= rollback(mydb
, vims
, rollback_list
)
848 if isinstance(e
, db_base_Exception
):
849 error_text
= "Exception at database"
850 elif isinstance(e
, KeyError):
851 error_text
= "KeyError exception "
852 e
.http_code
= HTTP_Internal_Server_Error
854 error_text
= "Exception at VIM"
855 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
856 #logger.error("start_scenario %s", error_text)
857 raise NfvoException(error_text
, e
.http_code
)
860 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
863 # Step 1. Check the VNF descriptor
864 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
865 # Step 2. Check tenant exist
867 if tenant_id
!= "any":
868 check_tenant(mydb
, tenant_id
)
869 if "tenant_id" in vnf_descriptor
["vnf"]:
870 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
871 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
874 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
875 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
876 if global_config
["auto_push_VNF_to_VIMs"]:
877 vims
= get_vim(mydb
, tenant_id
)
879 # Step 4. Review the descriptor and add missing fields
880 #print vnf_descriptor
881 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
882 vnf_name
= vnf_descriptor
['vnf']['name']
883 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
884 if "physical" in vnf_descriptor
['vnf']:
885 del vnf_descriptor
['vnf']['physical']
886 #print vnf_descriptor
888 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
889 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
890 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
892 #For each VNFC, we add it to the VNFCDict and we create a flavor.
893 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
894 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
896 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
897 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
899 VNFCitem
["name"] = vnfc
['name']
900 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
902 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
905 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
906 myflavorDict
["description"] = VNFCitem
["description"]
907 myflavorDict
["ram"] = vnfc
.get("ram", 0)
908 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
909 myflavorDict
["disk"] = vnfc
.get("disk", 1)
910 myflavorDict
["extended"] = {}
912 devices
= vnfc
.get("devices")
914 myflavorDict
["extended"]["devices"] = devices
917 # 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
918 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
920 # Previous code has been commented
921 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
922 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
923 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
924 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
926 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
928 # print "Error creating flavor: unknown processor model. Rollback successful."
929 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
931 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
932 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
934 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
935 myflavorDict
['extended']['numas'] = vnfc
['numas']
939 # Step 6.2 New flavors are created in the VIM
940 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
942 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
943 VNFCitem
["flavor_id"] = flavor_id
944 VNFCDict
[vnfc
['name']] = VNFCitem
946 logger
.debug("Creating new images in the VIM for each VNFC")
947 # Step 6.3 New images are created in the VIM
948 #For each VNFC, we must create the appropriate image.
949 #This "for" loop might be integrated with the previous one
950 #In case this integration is made, the VNFCDict might become a VNFClist.
951 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
952 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
954 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
955 image_dict
['universal_name']=vnfc
.get('image name')
956 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
957 image_dict
['location']=vnfc
.get('VNFC image')
958 #image_dict['new_location']=vnfc.get('image location')
959 image_dict
['checksum']=vnfc
.get('image checksum')
960 image_metadata_dict
= vnfc
.get('image metadata', None)
961 image_metadata_str
= None
962 if image_metadata_dict
is not None:
963 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
964 image_dict
['metadata']=image_metadata_str
965 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
966 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
967 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
968 VNFCDict
[vnfc
['name']]["image_id"] = image_id
969 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
970 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
971 if vnfc
.get("boot-data"):
972 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
974 # Step 7. Storing the VNF descriptor in the repository
975 if "descriptor" not in vnf_descriptor
["vnf"]:
976 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
978 # Step 8. Adding the VNF to the NFVO DB
979 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
981 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
982 _
, message
= rollback(mydb
, vims
, rollback_list
)
983 if isinstance(e
, db_base_Exception
):
984 error_text
= "Exception at database"
985 elif isinstance(e
, KeyError):
986 error_text
= "KeyError exception "
987 e
.http_code
= HTTP_Internal_Server_Error
989 error_text
= "Exception at VIM"
990 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
991 #logger.error("start_scenario %s", error_text)
992 raise NfvoException(error_text
, e
.http_code
)
995 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
996 #check valid tenant_id
997 check_tenant(mydb
, tenant_id
)
1000 if tenant_id
!= "any":
1001 where_or
["tenant_id"] = tenant_id
1002 where_or
["public"] = True
1003 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1006 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
1007 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
1008 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1009 data
={'vnf' : filtered_content
}
1011 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1012 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description', 'boot_data'),
1013 WHERE
={'vnfs.uuid': vnf_id
} )
1015 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1016 # change boot_data into boot-data
1018 if vm
.get("boot_data"):
1019 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1022 data
['vnf']['VNFC'] = content
1023 #TODO: GET all the information from a VNFC and include it in the output.
1026 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1027 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1028 WHERE
={'vnfs.uuid': vnf_id
} )
1029 data
['vnf']['nets'] = content
1031 #GET ip-profile for each net
1032 for net
in data
['vnf']['nets']:
1033 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1034 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1035 WHERE
={'net_id': net
["uuid"]} )
1036 if len(ipprofiles
)==1:
1037 net
["ip_profile"] = ipprofiles
[0]
1038 elif len(ipprofiles
)>1:
1039 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
1042 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1044 #GET External Interfaces
1045 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1046 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1047 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1048 WHERE
={'vnfs.uuid': vnf_id
},
1049 WHERE_NOT
={'interfaces.external_name': None} )
1051 data
['vnf']['external-connections'] = content
1056 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1057 # Check tenant exist
1058 if tenant_id
!= "any":
1059 check_tenant(mydb
, tenant_id
)
1060 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1061 vims
= get_vim(mydb
, tenant_id
)
1065 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1067 if tenant_id
!= "any":
1068 where_or
["tenant_id"] = tenant_id
1069 where_or
["public"] = True
1070 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1071 vnf_id
= vnf
["uuid"]
1073 # "Getting the list of flavors and tenants of the VNF"
1074 flavorList
= get_flavorlist(mydb
, vnf_id
)
1075 if len(flavorList
)==0:
1076 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1078 imageList
= get_imagelist(mydb
, vnf_id
)
1079 if len(imageList
)==0:
1080 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1082 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1084 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1087 for flavor
in flavorList
:
1088 #check if flavor is used by other vnf
1090 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1092 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1094 #flavor not used, must be deleted
1096 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
1097 for flavor_vim
in c
:
1098 if flavor_vim
["datacenter_id"] not in vims
:
1100 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
1102 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
1104 myvim
.delete_flavor(flavor_vim
["vim_id"])
1105 except vimconn
.vimconnNotFoundException
as e
:
1106 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
1107 except vimconn
.vimconnException
as e
:
1108 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1109 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1110 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
1111 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1112 mydb
.delete_row_by_id('flavors', flavor
)
1113 except db_base_Exception
as e
:
1114 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1115 undeletedItems
.append("flavor %s" % flavor
)
1118 for image
in imageList
:
1120 #check if image is used by other vnf
1121 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1123 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1125 #image not used, must be deleted
1127 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1129 if image_vim
["datacenter_id"] not in vims
:
1131 if image_vim
['created']=='false': #skip this image because not created by openmano
1133 myvim
=vims
[ image_vim
["datacenter_id"] ]
1135 myvim
.delete_image(image_vim
["vim_id"])
1136 except vimconn
.vimconnNotFoundException
as e
:
1137 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1138 except vimconn
.vimconnException
as e
:
1139 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1140 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1141 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1142 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1143 mydb
.delete_row_by_id('images', image
)
1144 except db_base_Exception
as e
:
1145 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1146 undeletedItems
.append("image %s" % image
)
1148 return vnf_id
+ " " + vnf
["name"]
1150 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1153 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1154 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1158 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1159 myvim
= vims
.values()[0]
1160 result
,servers
= myvim
.get_hosts_info()
1162 return result
, servers
1163 topology
= {'name':myvim
['name'] , 'servers': servers
}
1164 return result
, topology
1167 def get_hosts(mydb
, nfvo_tenant_id
):
1168 vims
= get_vim(mydb
, nfvo_tenant_id
)
1170 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1172 #print "nfvo.datacenter_action() error. Several datacenters found"
1173 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1174 myvim
= vims
.values()[0]
1176 hosts
= myvim
.get_hosts()
1177 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1179 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1181 server
={'name':host
['name'], 'vms':[]}
1182 for vm
in host
['instances']:
1183 #get internal name and model
1185 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1186 WHERE
={'vim_vm_id':vm
['id']} )
1188 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1190 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1192 except db_base_Exception
as e
:
1193 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1194 datacenter
['Datacenters'][0]['servers'].append(server
)
1195 #return -400, "en construccion"
1197 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1199 except vimconn
.vimconnException
as e
:
1200 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1203 def new_scenario(mydb
, tenant_id
, topo
):
1205 # result, vims = get_vim(mydb, tenant_id)
1207 # return result, vims
1209 if tenant_id
!= "any":
1210 check_tenant(mydb
, tenant_id
)
1211 if "tenant_id" in topo
:
1212 if topo
["tenant_id"] != tenant_id
:
1213 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1218 #1.1: get VNFs and external_networks (other_nets).
1220 other_nets
={} #external_networks, bridge_networks and data_networkds
1221 nodes
= topo
['topology']['nodes']
1222 for k
in nodes
.keys():
1223 if nodes
[k
]['type'] == 'VNF':
1225 vnfs
[k
]['ifaces'] = {}
1226 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1227 other_nets
[k
] = nodes
[k
]
1228 other_nets
[k
]['external']=True
1229 elif nodes
[k
]['type'] == 'network':
1230 other_nets
[k
] = nodes
[k
]
1231 other_nets
[k
]['external']=False
1234 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1235 for name
,vnf
in vnfs
.items():
1237 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1239 error_pos
= "'topology':'nodes':'" + name
+ "'"
1241 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1242 where
['uuid'] = vnf
['vnf_id']
1243 if 'VNF model' in vnf
:
1244 error_text
+= " 'VNF model' " + vnf
['VNF model']
1245 where
['name'] = vnf
['VNF model']
1247 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1249 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1255 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1257 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1258 vnf
['uuid']=vnf_db
[0]['uuid']
1259 vnf
['description']=vnf_db
[0]['description']
1260 #get external interfaces
1261 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1262 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1263 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1264 for ext_iface
in ext_ifaces
:
1265 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1267 #1.4 get list of connections
1268 conections
= topo
['topology']['connections']
1269 conections_list
= []
1270 conections_list_name
= []
1271 for k
in conections
.keys():
1272 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1273 ifaces_list
= conections
[k
]['nodes'].items()
1274 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1276 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1277 for k2
in conection_pair_list
:
1280 con_type
= conections
[k
].get("type", "link")
1281 if con_type
!= "link":
1283 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1284 other_nets
[k
] = {'external': False}
1285 if conections
[k
].get("graph"):
1286 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1287 ifaces_list
.append( (k
, None) )
1290 if con_type
== "external_network":
1291 other_nets
[k
]['external'] = True
1292 if conections
[k
].get("model"):
1293 other_nets
[k
]["model"] = conections
[k
]["model"]
1295 other_nets
[k
]["model"] = k
1296 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1297 other_nets
[k
]["model"] = con_type
1299 conections_list_name
.append(k
)
1300 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)
1301 #print set(ifaces_list)
1302 #check valid VNF and iface names
1303 for iface
in ifaces_list
:
1304 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1305 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1306 str(k
), iface
[0]), HTTP_Not_Found
)
1307 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1308 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1309 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1311 #1.5 unify connections from the pair list to a consolidated list
1313 while index
< len(conections_list
):
1315 while index2
< len(conections_list
):
1316 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1317 conections_list
[index
] |
= conections_list
[index2
]
1318 del conections_list
[index2
]
1319 del conections_list_name
[index2
]
1322 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1324 #for k in conections_list:
1329 #1.6 Delete non external nets
1330 # for k in other_nets.keys():
1331 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1332 # for con in conections_list:
1334 # for index in range(0,len(con)):
1335 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1336 # for index in delete_indexes:
1339 #1.7: Check external_ports are present at database table datacenter_nets
1340 for k
,net
in other_nets
.items():
1341 error_pos
= "'topology':'nodes':'" + k
+ "'"
1342 if net
['external']==False:
1343 if 'name' not in net
:
1345 if 'model' not in net
:
1346 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1347 if net
['model']=='bridge_net':
1348 net
['type']='bridge';
1349 elif net
['model']=='dataplane_net':
1352 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1354 #IF we do not want to check that external network exist at datacenter
1359 # if 'net_id' in net:
1360 # error_text += " 'net_id' " + net['net_id']
1361 # WHERE_['uuid'] = net['net_id']
1362 # if 'model' in net:
1363 # error_text += " 'model' " + net['model']
1364 # WHERE_['name'] = net['model']
1365 # if len(WHERE_) == 0:
1366 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1367 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1368 # FROM='datacenter_nets', WHERE=WHERE_ )
1370 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1372 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1373 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1375 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1376 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1377 # other_nets[k].update(net_db[0])
1380 net_nb
=0 #Number of nets
1381 for con
in conections_list
:
1382 #check if this is connected to a external net
1386 for index
in range(0,len(con
)):
1387 #check if this is connected to a external net
1388 for net_key
in other_nets
.keys():
1389 if con
[index
][0]==net_key
:
1390 if other_net_index
>=0:
1391 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1392 #print "nfvo.new_scenario " + error_text
1393 raise NfvoException(error_text
, HTTP_Bad_Request
)
1395 other_net_index
= index
1396 net_target
= net_key
1398 #print "other_net_index", other_net_index
1400 if other_net_index
>=0:
1401 del con
[other_net_index
]
1402 #IF we do not want to check that external network exist at datacenter
1403 if other_nets
[net_target
]['external'] :
1404 if "name" not in other_nets
[net_target
]:
1405 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1406 if other_nets
[net_target
]["type"] == "external_network":
1407 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1408 other_nets
[net_target
]["type"] = "data"
1410 other_nets
[net_target
]["type"] = "bridge"
1412 # if other_nets[net_target]['external'] :
1413 # 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
1414 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1415 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1416 # print "nfvo.new_scenario " + error_text
1417 # return -HTTP_Bad_Request, error_text
1420 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1423 net_type_bridge
=False
1425 net_target
= "__-__net"+str(net_nb
)
1426 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1427 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1430 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1431 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1432 if iface_type
=='mgmt' or iface_type
=='bridge':
1433 net_type_bridge
= True
1435 net_type_data
= True
1436 if net_type_bridge
and net_type_data
:
1437 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1438 #print "nfvo.new_scenario " + error_text
1439 raise NfvoException(error_text
, HTTP_Bad_Request
)
1440 elif net_type_bridge
:
1443 type_
='data' if len(con
)>2 else 'ptp'
1444 net_list
[net_target
]['type'] = type_
1447 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1448 #print "nfvo.new_scenario " + error_text
1450 raise NfvoException(error_text
, HTTP_Bad_Request
)
1452 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1453 #1.8.1 obtain management net
1454 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1455 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1456 #1.8.2 check all interfaces from all vnfs
1458 add_mgmt_net
= False
1459 for vnf
in vnfs
.values():
1460 for iface
in vnf
['ifaces'].values():
1461 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1462 #iface not connected
1463 iface
['net_key'] = 'mgmt'
1465 if add_mgmt_net
and 'mgmt' not in net_list
:
1466 net_list
['mgmt']=mgmt_net
[0]
1467 net_list
['mgmt']['external']=True
1468 net_list
['mgmt']['graph']={'visible':False}
1470 net_list
.update(other_nets
)
1472 #print 'net_list', net_list
1477 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1478 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1479 'tenant_id':tenant_id
, 'name':topo
['name'],
1480 'description':topo
.get('description',topo
['name']),
1481 'public': topo
.get('public', False)
1487 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
1488 """ This creates a new scenario for version 0.2 and 0.3"""
1489 scenario
= scenario_dict
["scenario"]
1490 if tenant_id
!= "any":
1491 check_tenant(mydb
, tenant_id
)
1492 if "tenant_id" in scenario
:
1493 if scenario
["tenant_id"] != tenant_id
:
1494 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1495 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1496 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1500 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
1501 for name
,vnf
in scenario
["vnfs"].iteritems():
1503 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1505 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1507 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1508 where
['uuid'] = vnf
['vnf_id']
1509 if 'vnf_name' in vnf
:
1510 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1511 where
['name'] = vnf
['vnf_name']
1513 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1514 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
1519 if len(vnf_db
) == 0:
1520 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1521 elif len(vnf_db
) > 1:
1522 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1523 vnf
['uuid'] = vnf_db
[0]['uuid']
1524 vnf
['description'] = vnf_db
[0]['description']
1526 # get external interfaces
1527 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
1528 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1529 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name': None} )
1530 for ext_iface
in ext_ifaces
:
1531 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
1532 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1534 # 2: Insert net_key and ip_address at every vnf interface
1535 for net_name
, net
in scenario
["networks"].items():
1536 net_type_bridge
= False
1537 net_type_data
= False
1538 for iface_dict
in net
["interfaces"]:
1539 if version
== "0.2":
1540 temp_dict
= iface_dict
1542 elif version
== "0.3":
1543 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
1544 ip_address
= iface_dict
.get('ip_address', None)
1545 for vnf
, iface
in temp_dict
.items():
1546 if vnf
not in scenario
["vnfs"]:
1547 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
1549 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1550 raise NfvoException(error_text
, HTTP_Not_Found
)
1551 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1552 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
1553 .format(net_name
, iface
)
1554 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1555 raise NfvoException(error_text
, HTTP_Bad_Request
)
1556 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1557 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
1558 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1559 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1560 raise NfvoException(error_text
, HTTP_Bad_Request
)
1561 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1562 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
1563 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1564 if iface_type
== 'mgmt' or iface_type
== 'bridge':
1565 net_type_bridge
= True
1567 net_type_data
= True
1569 if net_type_bridge
and net_type_data
:
1570 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
1572 # logger.debug("nfvo.new_scenario " + error_text)
1573 raise NfvoException(error_text
, HTTP_Bad_Request
)
1574 elif net_type_bridge
:
1577 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
1579 if net
.get("implementation"): # for v0.3
1580 if type_
== "bridge" and net
["implementation"] == "underlay":
1581 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
1582 "'network':'{}'".format(net_name
)
1583 # logger.debug(error_text)
1584 raise NfvoException(error_text
, HTTP_Bad_Request
)
1585 elif type_
!= "bridge" and net
["implementation"] == "overlay":
1586 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
1587 "'network':'{}'".format(net_name
)
1588 # logger.debug(error_text)
1589 raise NfvoException(error_text
, HTTP_Bad_Request
)
1590 net
.pop("implementation")
1591 if "type" in net
and version
== "0.3": # for v0.3
1592 if type_
== "data" and net
["type"] == "e-line":
1593 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
1594 "'e-line' at 'network':'{}'".format(net_name
)
1595 # logger.debug(error_text)
1596 raise NfvoException(error_text
, HTTP_Bad_Request
)
1597 elif type_
== "ptp" and net
["type"] == "e-lan":
1601 net
['name'] = net_name
1602 net
['external'] = net
.get('external', False)
1604 # 3: insert at database
1605 scenario
["nets"] = scenario
["networks"]
1606 scenario
['tenant_id'] = tenant_id
1607 scenario_id
= mydb
.new_scenario(scenario
)
1611 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1612 data
["uuid"] = scenario_id
1613 data
["tenant_id"] = tenant_id
1614 c
= mydb
.edit_scenario( data
)
1618 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1619 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1620 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
1621 vims
= {datacenter_id
: myvim
}
1622 myvim_tenant
= myvim
['tenant_id']
1623 datacenter_name
= myvim
['name']
1627 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1628 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1629 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
1630 scenarioDict
['datacenter_id'] = datacenter_id
1631 #print '================scenarioDict======================='
1632 #print json.dumps(scenarioDict, indent=4)
1633 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1635 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1636 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1638 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1639 auxNetDict
['scenario'] = {}
1641 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1642 for sce_net
in scenarioDict
['nets']:
1643 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1645 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1646 myNetName
= myNetName
[0:255] #limit length
1647 myNetType
= sce_net
['type']
1649 myNetDict
["name"] = myNetName
1650 myNetDict
["type"] = myNetType
1651 myNetDict
["tenant_id"] = myvim_tenant
1652 myNetIPProfile
= sce_net
.get('ip_profile', None)
1654 #We should use the dictionary as input parameter for new_network
1656 if not sce_net
["external"]:
1657 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1658 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1659 sce_net
['vim_id'] = network_id
1660 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1661 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1662 sce_net
["created"] = True
1664 if sce_net
['vim_id'] == None:
1665 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1666 _
, message
= rollback(mydb
, vims
, rollbackList
)
1667 logger
.error("nfvo.start_scenario: %s", error_text
)
1668 raise NfvoException(error_text
, HTTP_Bad_Request
)
1669 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1670 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1672 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1673 #For each vnf net, we create it and we add it to instanceNetlist.
1675 for sce_vnf
in scenarioDict
['vnfs']:
1676 for net
in sce_vnf
['nets']:
1677 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1679 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1680 myNetName
= myNetName
[0:255] #limit length
1681 myNetType
= net
['type']
1683 myNetDict
["name"] = myNetName
1684 myNetDict
["type"] = myNetType
1685 myNetDict
["tenant_id"] = myvim_tenant
1686 myNetIPProfile
= net
.get('ip_profile', None)
1689 #We should use the dictionary as input parameter for new_network
1690 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1691 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1692 net
['vim_id'] = network_id
1693 if sce_vnf
['uuid'] not in auxNetDict
:
1694 auxNetDict
[sce_vnf
['uuid']] = {}
1695 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1696 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1697 net
["created"] = True
1699 #print "auxNetDict:"
1700 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1702 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1703 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1705 for sce_vnf
in scenarioDict
['vnfs']:
1706 vnf_availability_zones
= []
1707 for vm
in sce_vnf
['vms']:
1708 vm_av
= vm
.get('availability_zone')
1709 if vm_av
and vm_av
not in vnf_availability_zones
:
1710 vnf_availability_zones
.append(vm_av
)
1712 # check if there is enough availability zones available at vim level.
1713 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
1714 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
1715 raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request
)
1717 for vm
in sce_vnf
['vms']:
1720 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1721 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
1722 #myVMDict['description'] = vm['description']
1723 myVMDict
['description'] = myVMDict
['name'][0:99]
1725 myVMDict
['start'] = "no"
1726 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1727 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1729 #create image at vim in case it not exist
1730 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1731 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1732 vm
['vim_image_id'] = image_id
1734 #create flavor at vim in case it not exist
1735 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1736 if flavor_dict
['extended']!=None:
1737 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1738 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1739 vm
['vim_flavor_id'] = flavor_id
1742 myVMDict
['imageRef'] = vm
['vim_image_id']
1743 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1744 myVMDict
['networks'] = []
1745 for iface
in vm
['interfaces']:
1747 if iface
['type']=="data":
1748 netDict
['type'] = iface
['model']
1749 elif "model" in iface
and iface
["model"]!=None:
1750 netDict
['model']=iface
['model']
1751 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1752 #discover type of interface looking at flavor
1753 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1754 for flavor_iface
in numa
.get('interfaces',[]):
1755 if flavor_iface
.get('name') == iface
['internal_name']:
1756 if flavor_iface
['dedicated'] == 'yes':
1757 netDict
['type']="PF" #passthrough
1758 elif flavor_iface
['dedicated'] == 'no':
1759 netDict
['type']="VF" #siov
1760 elif flavor_iface
['dedicated'] == 'yes:sriov':
1761 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1762 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1764 netDict
["use"]=iface
['type']
1765 if netDict
["use"]=="data" and not netDict
.get("type"):
1766 #print "netDict", netDict
1767 #print "iface", iface
1768 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'])
1769 if flavor_dict
.get('extended')==None:
1770 raise NfvoException(e_text
+ "After database migration some information is not available. \
1771 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1773 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1774 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1775 netDict
["type"]="virtual"
1776 if "vpci" in iface
and iface
["vpci"] is not None:
1777 netDict
['vpci'] = iface
['vpci']
1778 if "mac" in iface
and iface
["mac"] is not None:
1779 netDict
['mac_address'] = iface
['mac']
1780 if "port-security" in iface
and iface
["port-security"] is not None:
1781 netDict
['port_security'] = iface
['port-security']
1782 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
1783 netDict
['floating_ip'] = iface
['floating-ip']
1784 netDict
['name'] = iface
['internal_name']
1785 if iface
['net_id'] is None:
1786 for vnf_iface
in sce_vnf
["interfaces"]:
1789 if vnf_iface
['interface_id']==iface
['uuid']:
1790 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1793 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1794 #skip bridge ifaces not connected to any net
1795 #if 'net_id' not in netDict or netDict['net_id']==None:
1797 myVMDict
['networks'].append(netDict
)
1798 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1799 #print myVMDict['name']
1800 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1801 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1802 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1804 if 'availability_zone' in myVMDict
:
1805 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
1809 vm_id
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
1810 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
1811 availability_zone_index
=av_index
,
1812 availability_zone_list
=vnf_availability_zones
)
1813 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1814 vm
['vim_id'] = vm_id
1815 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1816 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1817 for net
in myVMDict
['networks']:
1819 for iface
in vm
['interfaces']:
1820 if net
["name"]==iface
["internal_name"]:
1821 iface
["vim_id"]=net
["vim_id"]
1824 logger
.debug("start scenario Deployment done")
1825 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1826 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1827 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1828 return mydb
.get_instance_scenario(instance_id
)
1830 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1831 _
, message
= rollback(mydb
, vims
, rollbackList
)
1832 if isinstance(e
, db_base_Exception
):
1833 error_text
= "Exception at database"
1835 error_text
= "Exception at VIM"
1836 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1837 #logger.error("start_scenario %s", error_text)
1838 raise NfvoException(error_text
, e
.http_code
)
1841 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
1842 """ join the cloud config information into cloud_config_preserve.
1843 In case of conflict cloud_config_preserve preserves
1846 if not cloud_config_preserve
and not cloud_config
:
1849 new_cloud_config
= {"key-pairs":[], "users":[]}
1851 if cloud_config_preserve
:
1852 for key
in cloud_config_preserve
.get("key-pairs", () ):
1853 if key
not in new_cloud_config
["key-pairs"]:
1854 new_cloud_config
["key-pairs"].append(key
)
1856 for key
in cloud_config
.get("key-pairs", () ):
1857 if key
not in new_cloud_config
["key-pairs"]:
1858 new_cloud_config
["key-pairs"].append(key
)
1859 if not new_cloud_config
["key-pairs"]:
1860 del new_cloud_config
["key-pairs"]
1864 new_cloud_config
["users"] += cloud_config
.get("users", () )
1865 if cloud_config_preserve
:
1866 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
1867 index_to_delete
= []
1868 users
= new_cloud_config
.get("users", [])
1869 for index0
in range(0,len(users
)):
1870 if index0
in index_to_delete
:
1872 for index1
in range(index0
+1,len(users
)):
1873 if index1
in index_to_delete
:
1875 if users
[index0
]["name"] == users
[index1
]["name"]:
1876 index_to_delete
.append(index1
)
1877 for key
in users
[index1
].get("key-pairs",()):
1878 if "key-pairs" not in users
[index0
]:
1879 users
[index0
]["key-pairs"] = [key
]
1880 elif key
not in users
[index0
]["key-pairs"]:
1881 users
[index0
]["key-pairs"].append(key
)
1882 index_to_delete
.sort(reverse
=True)
1883 for index
in index_to_delete
:
1885 if not new_cloud_config
["users"]:
1886 del new_cloud_config
["users"]
1889 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
1890 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
1891 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
1892 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
1895 new_cloud_config
["user-data"] = []
1896 if cloud_config
and cloud_config
.get("user-data"):
1897 if isinstance(cloud_config
["user-data"], list):
1898 new_cloud_config
["user-data"] += cloud_config
["user-data"]
1900 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
1901 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
1902 if isinstance(cloud_config_preserve
["user-data"], list):
1903 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
1905 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
1906 if not new_cloud_config
["user-data"]:
1907 del new_cloud_config
["user-data"]
1910 new_cloud_config
["config-files"] = []
1911 if cloud_config
and cloud_config
.get("config-files") != None:
1912 new_cloud_config
["config-files"] += cloud_config
["config-files"]
1913 if cloud_config_preserve
:
1914 for file in cloud_config_preserve
.get("config-files", ()):
1915 for index
in range(0, len(new_cloud_config
["config-files"])):
1916 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
1917 new_cloud_config
["config-files"][index
] = file
1920 new_cloud_config
["config-files"].append(file)
1921 if not new_cloud_config
["config-files"]:
1922 del new_cloud_config
["config-files"]
1923 return new_cloud_config
1926 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
1927 datacenter_id
= None
1928 datacenter_name
= None
1931 if datacenter_tenant_id
:
1932 thread_id
= datacenter_tenant_id
1933 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
1935 where_
={"td.nfvo_tenant_id": tenant_id
}
1936 if datacenter_id_name
:
1937 if utils
.check_valid_uuid(datacenter_id_name
):
1938 datacenter_id
= datacenter_id_name
1939 where_
["dt.datacenter_id"] = datacenter_id
1941 datacenter_name
= datacenter_id_name
1942 where_
["d.name"] = datacenter_name
1943 if datacenter_tenant_id
:
1944 where_
["dt.uuid"] = datacenter_tenant_id
1945 datacenters
= mydb
.get_rows(
1946 SELECT
=("dt.uuid as datacenter_tenant_id",),
1947 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
1948 "join datacenters as d on d.uuid=dt.datacenter_id",
1950 if len(datacenters
) > 1:
1951 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1953 thread_id
= datacenters
[0]["datacenter_tenant_id"]
1954 thread
= vim_threads
["running"].get(thread_id
)
1956 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1957 return thread_id
, thread
1958 except db_base_Exception
as e
:
1959 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
1962 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1963 datacenter_id
= None
1964 datacenter_name
= None
1965 if datacenter_id_name
:
1966 if utils
.check_valid_uuid(datacenter_id_name
):
1967 datacenter_id
= datacenter_id_name
1969 datacenter_name
= datacenter_id_name
1970 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1972 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1974 #print "nfvo.datacenter_action() error. Several datacenters found"
1975 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1976 return vims
.keys()[0], vims
.values()[0]
1980 '''Takes dict d and updates it with the values in dict u.'''
1981 '''It merges all depth levels'''
1982 for k
, v
in u
.iteritems():
1983 if isinstance(v
, collections
.Mapping
):
1984 r
= update(d
.get(k
, {}), v
)
1991 def create_instance(mydb
, tenant_id
, instance_dict
):
1992 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1993 # logger.debug("Creating instance...")
1994 scenario
= instance_dict
["scenario"]
1996 #find main datacenter
1998 myvim_threads_id
= {}
2001 datacenter
= instance_dict
.get("datacenter")
2002 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2003 myvims
[default_datacenter_id
] = vim
2004 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
2005 tasks_to_launch
[myvim_threads_id
[default_datacenter_id
]] = []
2006 #myvim_tenant = myvim['tenant_id']
2007 # default_datacenter_name = vim['name']
2010 #print "Checking that the scenario exists and getting the scenario dictionary"
2011 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
2013 #logger.debug(">>>>>>> Dictionaries before merging")
2014 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
2015 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
2018 instance_name
= instance_dict
["name"]
2019 instance_uuid
= str(uuid4())
2020 uuid_list
.append(instance_uuid
)
2021 db_instance_scenario
= {
2022 "uuid": instance_uuid
,
2023 "name": instance_name
,
2024 "tenant_id": tenant_id
,
2025 "scenario_id": scenarioDict
['uuid'],
2026 "datacenter_id": default_datacenter_id
,
2027 # filled bellow 'datacenter_tenant_id'
2028 "description": instance_dict
.get("description"),
2031 if scenarioDict
.get("cloud-config"):
2032 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
2033 default_flow_style
=True, width
=256)
2035 vnf_net2instance
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2036 sce_net2instance
= {}
2037 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2038 auxNetDict
['scenario'] = {}
2040 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
2042 # 0 check correct parameters
2043 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2045 for scenario_net
in scenarioDict
['nets']:
2046 if net_name
== scenario_net
["name"]:
2050 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
2051 if "sites" not in net_instance_desc
:
2052 net_instance_desc
["sites"] = [ {} ]
2053 site_without_datacenter_field
= False
2054 for site
in net_instance_desc
["sites"]:
2055 if site
.get("datacenter"):
2056 if site
["datacenter"] not in myvims
:
2057 #Add this datacenter to myvims
2058 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
2060 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
2061 tasks_to_launch
[myvim_threads_id
[d
]] = []
2062 site
["datacenter"] = d
#change name to id
2064 if site_without_datacenter_field
:
2065 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
2066 site_without_datacenter_field
= True
2067 site
["datacenter"] = default_datacenter_id
#change name to id
2069 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
2071 for scenario_vnf
in scenarioDict
['vnfs']:
2072 if vnf_name
== scenario_vnf
['name']:
2076 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
2077 if "datacenter" in vnf_instance_desc
:
2078 # Add this datacenter to myvims
2079 if vnf_instance_desc
["datacenter"] not in myvims
:
2080 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2082 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2083 tasks_to_launch
[myvim_threads_id
[d
]] = []
2084 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2086 #0.1 parse cloud-config parameters
2087 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2089 #0.2 merge instance information into scenario
2090 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2091 #However, this is not possible yet.
2092 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2093 for scenario_net
in scenarioDict
['nets']:
2094 if net_name
== scenario_net
["name"]:
2095 if 'ip-profile' in net_instance_desc
:
2096 # translate from input format to database format
2097 ipprofile_in
= net_instance_desc
['ip-profile']
2099 ipprofile_db
['subnet_address'] = ipprofile_in
.get('subnet-address')
2100 ipprofile_db
['ip_version'] = ipprofile_in
.get('ip-version', 'IPv4')
2101 ipprofile_db
['gateway_address'] = ipprofile_in
.get('gateway-address')
2102 ipprofile_db
['dns_address'] = ipprofile_in
.get('dns-address')
2103 if isinstance(ipprofile_db
['dns_address'], (list, tuple)):
2104 ipprofile_db
['dns_address'] = ";".join(ipprofile_db
['dns_address'])
2105 if 'dhcp' in ipprofile_in
:
2106 ipprofile_db
['dhcp_start_address'] = ipprofile_in
['dhcp'].get('start-address')
2107 ipprofile_db
['dhcp_enabled'] = ipprofile_in
['dhcp'].get('enabled', True)
2108 ipprofile_db
['dhcp_count'] = ipprofile_in
['dhcp'].get('count' )
2109 if 'ip_profile' not in scenario_net
:
2110 scenario_net
['ip_profile'] = ipprofile_db
2112 update(scenario_net
['ip_profile'], ipprofile_db
)
2113 for interface
in net_instance_desc
.get('interfaces', () ):
2114 if 'ip_address' in interface
:
2115 for vnf
in scenarioDict
['vnfs']:
2116 if interface
['vnf'] == vnf
['name']:
2117 for vnf_interface
in vnf
['interfaces']:
2118 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2119 vnf_interface
['ip_address']=interface
['ip_address']
2121 #logger.debug(">>>>>>>> Merged dictionary")
2122 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
2124 # 1. Creating new nets (sce_nets) in the VIM"
2125 db_instance_nets
= []
2126 for sce_net
in scenarioDict
['nets']:
2127 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
2128 net_name
= descriptor_net
.get("vim-network-name")
2129 sce_net2instance
[sce_net
['uuid']] = {}
2130 auxNetDict
['scenario'][sce_net
['uuid']] = {}
2132 sites
= descriptor_net
.get("sites", [ {} ])
2134 if site
.get("datacenter"):
2135 vim
= myvims
[ site
["datacenter"] ]
2136 datacenter_id
= site
["datacenter"]
2137 myvim_thread_id
= myvim_threads_id
[ site
["datacenter"] ]
2139 vim
= myvims
[ default_datacenter_id
]
2140 datacenter_id
= default_datacenter_id
2141 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2142 net_type
= sce_net
['type']
2143 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
2144 if sce_net
["external"]:
2146 net_name
= sce_net
["name"]
2147 if "netmap-use" in site
or "netmap-create" in site
:
2148 create_network
= False
2149 lookfor_network
= False
2150 if "netmap-use" in site
:
2151 lookfor_network
= True
2152 if utils
.check_valid_uuid(site
["netmap-use"]):
2153 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2154 lookfor_filter
["id"] = site
["netmap-use"]
2156 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2157 lookfor_filter
["name"] = site
["netmap-use"]
2158 if "netmap-create" in site
:
2159 create_network
= True
2160 net_vim_name
= net_name
2161 if site
["netmap-create"]:
2162 net_vim_name
= site
["netmap-create"]
2164 elif sce_net
['vim_id'] != None:
2165 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
2166 create_network
= False
2167 lookfor_network
= True
2168 lookfor_filter
["id"] = sce_net
['vim_id']
2169 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
2170 #look for network at datacenter and return error
2172 #There is not a netmap, look at datacenter for a net with this name and create if not found
2173 create_network
= True
2174 lookfor_network
= True
2175 lookfor_filter
["name"] = sce_net
["name"]
2176 net_vim_name
= sce_net
["name"]
2177 filter_text
= "scenario name '%s'" % sce_net
["name"]
2180 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
2181 net_name
= net_name
[:255] #limit length
2182 net_vim_name
= net_name
2183 create_network
= True
2184 lookfor_network
= False
2187 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
2188 if len(vim_nets
) > 1:
2189 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2190 elif len(vim_nets
) == 0:
2191 if not create_network
:
2192 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2194 vim_id
= vim_nets
[0]['id']
2195 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
2196 create_network
= False
2198 #if network is not external
2199 task
= new_task("new-net", (net_vim_name
, net_type
, sce_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_vim_name, net_type, sce_net.get('ip_profile',None))
2205 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = task_id
2206 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':task_id
})
2207 sce_net
["created"] = True
2209 # fill database content
2210 net_uuid
= str(uuid4())
2211 uuid_list
.append(net_uuid
)
2212 sce_net2instance
[sce_net
['uuid']][datacenter_id
] = net_uuid
2215 'vim_net_id': vim_id
,
2216 "instance_scenario_id": instance_uuid
,
2217 "sce_net_id": sce_net
["uuid"],
2218 "created": create_network
,
2219 'datacenter_id': datacenter_id
,
2220 'datacenter_tenant_id': myvim_thread_id
,
2221 'status': 'BUILD' if create_network
else "ACTIVE"
2223 db_instance_nets
.append(db_net
)
2224 if 'ip_profile' in sce_net
:
2226 'instance_net_id': net_uuid
,
2227 'ip_version': sce_net
['ip_profile']['ip_version'],
2228 'subnet_address': sce_net
['ip_profile']['subnet_address'],
2229 'gateway_address': sce_net
['ip_profile']['gateway_address'],
2230 'dns_address': sce_net
['ip_profile']['dns_address'],
2231 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
2232 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
2233 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
2235 db_ip_profiles
.append(db_ip_profile
)
2237 # 2. Creating new nets (vnf internal nets) in the VIM"
2238 # For each vnf net, we create it and we add it to instanceNetlist.
2239 for sce_vnf
in scenarioDict
['vnfs']:
2240 for net
in sce_vnf
['nets']:
2241 if sce_vnf
.get("datacenter"):
2242 vim
= myvims
[ sce_vnf
["datacenter"] ]
2243 datacenter_id
= sce_vnf
["datacenter"]
2244 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"]]
2246 vim
= myvims
[ default_datacenter_id
]
2247 datacenter_id
= default_datacenter_id
2248 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2249 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
2250 net_name
= descriptor_net
.get("name")
2252 net_name
= "%s.%s" %(instance_name
, net
["name"])
2253 net_name
= net_name
[:255] #limit length
2254 net_type
= net
['type']
2255 task
= new_task("new-net", (net_name
, net_type
, net
.get('ip_profile',None)))
2256 task_id
= task
["id"]
2257 instance_tasks
[task_id
] = task
2258 tasks_to_launch
[myvim_thread_id
].append(task
)
2259 # network_id = vim.new_network(net_name, net_type, net.get('ip_profile',None))
2261 if sce_vnf
['uuid'] not in vnf_net2instance
:
2262 vnf_net2instance
[sce_vnf
['uuid']] = {}
2263 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = task_id
2264 if sce_vnf
['uuid'] not in auxNetDict
:
2265 auxNetDict
[sce_vnf
['uuid']] = {}
2266 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = task_id
2267 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':task_id
})
2268 net
["created"] = True
2270 # fill database content
2271 net_uuid
= str(uuid4())
2272 uuid_list
.append(net_uuid
)
2273 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
2276 'vim_net_id': vim_id
,
2277 "instance_scenario_id": instance_uuid
,
2278 "net_id": net
["uuid"],
2280 'datacenter_id': datacenter_id
,
2281 'datacenter_tenant_id': myvim_thread_id
,
2283 db_instance_nets
.append(db_net
)
2284 if 'ip_profile' in net
:
2286 'instance_net_id': net_uuid
,
2287 'ip_version': net
['ip_profile']['ip_version'],
2288 'subnet_address': net
['ip_profile']['subnet_address'],
2289 'gateway_address': net
['ip_profile']['gateway_address'],
2290 'dns_address': net
['ip_profile']['dns_address'],
2291 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
2292 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
2293 'dhcp_count': net
['ip_profile']['dhcp_count'],
2295 db_ip_profiles
.append(db_ip_profile
)
2297 #print "vnf_net2instance:"
2298 #print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
2300 # 3. Creating new vm instances in the VIM
2301 db_instance_vnfs
= []
2302 db_instance_vms
= []
2303 db_instance_interfaces
= []
2304 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2305 sce_vnf_list
= sorted(scenarioDict
['vnfs'], key
=lambda k
: k
['name'])
2306 #for sce_vnf in scenarioDict['vnfs']:
2307 for sce_vnf
in sce_vnf_list
:
2308 vnf_availability_zones
= []
2309 for vm
in sce_vnf
['vms']:
2310 vm_av
= vm
.get('availability_zone')
2311 if vm_av
and vm_av
not in vnf_availability_zones
:
2312 vnf_availability_zones
.append(vm_av
)
2314 # check if there is enough availability zones available at vim level.
2315 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2316 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2317 raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request
)
2319 if sce_vnf
.get("datacenter"):
2320 vim
= myvims
[ sce_vnf
["datacenter"] ]
2321 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"] ]
2322 datacenter_id
= sce_vnf
["datacenter"]
2324 vim
= myvims
[ default_datacenter_id
]
2325 myvim_thread_id
= myvim_threads_id
[ default_datacenter_id
]
2326 datacenter_id
= default_datacenter_id
2327 sce_vnf
["datacenter_id"] = datacenter_id
2330 vnf_uuid
= str(uuid4())
2331 uuid_list
.append(vnf_uuid
)
2334 'instance_scenario_id': instance_uuid
,
2335 'vnf_id': sce_vnf
['vnf_id'],
2336 'sce_vnf_id': sce_vnf
['uuid'],
2337 'datacenter_id': datacenter_id
,
2338 'datacenter_tenant_id': myvim_thread_id
,
2340 db_instance_vnfs
.append(db_instance_vnf
)
2342 for vm
in sce_vnf
['vms']:
2344 myVMDict
['name'] = "{}.{}.{}".format(instance_name
[:64], sce_vnf
['name'][:64], vm
["name"][:64])
2345 myVMDict
['description'] = myVMDict
['name'][0:99]
2347 # myVMDict['start'] = "no"
2348 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2349 #create image at vim in case it not exist
2350 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2351 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2352 vm
['vim_image_id'] = image_id
2354 #create flavor at vim in case it not exist
2355 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2356 if flavor_dict
['extended']!=None:
2357 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2358 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
2360 #Obtain information for additional disks
2361 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
2362 if not extended_flavor_dict
:
2363 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
2366 #extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
2367 myVMDict
['disks'] = None
2368 extended_info
= extended_flavor_dict
[0]['extended']
2369 if extended_info
!= None:
2370 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
2371 if 'disks' in extended_flavor_dict_yaml
:
2372 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
2374 vm
['vim_flavor_id'] = flavor_id
2375 myVMDict
['imageRef'] = vm
['vim_image_id']
2376 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2377 myVMDict
['availability_zone'] = vm
.get('availability_zone')
2378 myVMDict
['networks'] = []
2380 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
2382 for iface
in vm
['interfaces']:
2384 if iface
['type']=="data":
2385 netDict
['type'] = iface
['model']
2386 elif "model" in iface
and iface
["model"]!=None:
2387 netDict
['model']=iface
['model']
2388 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2389 #discover type of interface looking at flavor
2390 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2391 for flavor_iface
in numa
.get('interfaces',[]):
2392 if flavor_iface
.get('name') == iface
['internal_name']:
2393 if flavor_iface
['dedicated'] == 'yes':
2394 netDict
['type']="PF" #passthrough
2395 elif flavor_iface
['dedicated'] == 'no':
2396 netDict
['type']="VF" #siov
2397 elif flavor_iface
['dedicated'] == 'yes:sriov':
2398 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2399 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2401 netDict
["use"]=iface
['type']
2402 if netDict
["use"]=="data" and not netDict
.get("type"):
2403 #print "netDict", netDict
2404 #print "iface", iface
2405 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'])
2406 if flavor_dict
.get('extended')==None:
2407 raise NfvoException(e_text
+ "After database migration some information is not available. \
2408 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2410 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2411 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2412 netDict
["type"]="virtual"
2413 if "vpci" in iface
and iface
["vpci"] is not None:
2414 netDict
['vpci'] = iface
['vpci']
2415 if "mac" in iface
and iface
["mac"] is not None:
2416 netDict
['mac_address'] = iface
['mac']
2417 if "port-security" in iface
and iface
["port-security"] is not None:
2418 netDict
['port_security'] = iface
['port-security']
2419 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2420 netDict
['floating_ip'] = iface
['floating-ip']
2421 netDict
['name'] = iface
['internal_name']
2422 if iface
['net_id'] is None:
2423 for vnf_iface
in sce_vnf
["interfaces"]:
2426 if vnf_iface
['interface_id']==iface
['uuid']:
2427 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
2428 instance_net_id
= sce_net2instance
[ vnf_iface
['sce_net_id'] ][datacenter_id
]
2431 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2432 instance_net_id
= vnf_net2instance
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2433 if netDict
.get('net_id') and is_task_id(netDict
['net_id']):
2434 task_depends
[netDict
['net_id']] = instance_tasks
[netDict
['net_id']]
2435 #skip bridge ifaces not connected to any net
2436 #if 'net_id' not in netDict or netDict['net_id']==None:
2438 myVMDict
['networks'].append(netDict
)
2441 # 'instance_vm_id': instance_vm_uuid,
2442 "instance_net_id": instance_net_id
,
2443 'interface_id': iface
['uuid'],
2444 # 'vim_interface_id': ,
2445 'type': 'external' if iface
['external_name'] is not None else 'internal',
2446 'ip_address': iface
.get('ip_address'),
2447 'floating_ip': int(iface
.get('floating-ip', False)),
2448 'port_security': int(iface
.get('port-security', True))
2450 db_vm_ifaces
.append(db_vm_iface
)
2451 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2452 # print myVMDict['name']
2453 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2454 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2455 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2456 if vm
.get("boot_data"):
2457 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
2459 cloud_config_vm
= cloud_config
2460 if myVMDict
.get('availability_zone'):
2461 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2464 for vm_index
in range(0, vm
.get('count', 1)):
2466 if vm
.get('count', 1) > 1:
2467 vm_index_name
+= "." + chr(97 + vm_index
)
2468 task
= new_task("new-vm", (myVMDict
['name']+vm_index_name
, myVMDict
['description'],
2469 myVMDict
.get('start', None), myVMDict
['imageRef'],
2470 myVMDict
['flavorRef'], myVMDict
['networks'],
2471 cloud_config_vm
, myVMDict
['disks'], av_index
,
2472 vnf_availability_zones
), depends
=task_depends
)
2473 instance_tasks
[task
["id"]] = task
2474 tasks_to_launch
[myvim_thread_id
].append(task
)
2476 vm
['vim_id'] = vm_id
2477 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2478 # put interface uuid back to scenario[vnfs][vms[[interfaces]
2479 for net
in myVMDict
['networks']:
2481 for iface
in vm
['interfaces']:
2482 if net
["name"]==iface
["internal_name"]:
2483 iface
["vim_id"]=net
["vim_id"]
2485 vm_uuid
= str(uuid4())
2486 uuid_list
.append(vm_uuid
)
2489 'instance_vnf_id': vnf_uuid
,
2491 "vm_id": vm
["uuid"],
2494 db_instance_vms
.append(db_vm
)
2495 for db_vm_iface
in db_vm_ifaces
:
2496 iface_uuid
= str(uuid4())
2497 uuid_list
.append(iface_uuid
)
2498 db_vm_iface_instance
= {
2500 "instance_vm_id": vm_uuid
2502 db_vm_iface_instance
.update(db_vm_iface
)
2503 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
2504 ip
= db_vm_iface_instance
.get("ip_address")
2509 ip
= ip
[i
:] + str(int(ip
[:i
]) +1)
2510 db_vm_iface_instance
["ip_address"] = ip
2512 db_vm_iface_instance
["ip_address"] = None
2513 db_instance_interfaces
.append(db_vm_iface_instance
)
2515 scenarioDict
["datacenter2tenant"] = myvim_threads_id
2517 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
2518 db_instance_scenario
['datacenter_id'] = default_datacenter_id
2520 {"instance_scenarios": db_instance_scenario
},
2521 {"instance_vnfs": db_instance_vnfs
},
2522 {"instance_nets": db_instance_nets
},
2523 {"ip_profiles": db_ip_profiles
},
2524 {"instance_vms": db_instance_vms
},
2525 {"instance_interfaces": db_instance_interfaces
},
2528 logger
.debug("create_instance Deployment done scenarioDict: %s",
2529 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2530 mydb
.new_rows(db_tables
, uuid_list
)
2531 for myvim_thread_id
,task_list
in tasks_to_launch
.items():
2532 for task
in task_list
:
2533 vim_threads
["running"][myvim_thread_id
].insert_task(task
)
2535 global_instance_tasks
[instance_uuid
] = instance_tasks
2536 # Update database with those ended instance_tasks
2537 # for task in instance_tasks.values():
2538 # if task["status"] == "ok":
2539 # if task["name"] == "new-vm":
2540 # mydb.update_rows("instance_vms", UPDATE={"vim_vm_id": task["result"]},
2541 # WHERE={"vim_vm_id": task["id"]})
2542 # elif task["name"] == "new-net":
2543 # mydb.update_rows("instance_nets", UPDATE={"vim_net_id": task["result"]},
2544 # WHERE={"vim_net_id": task["id"]})
2545 return mydb
.get_instance_scenario(instance_uuid
)
2546 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2547 message
= rollback(mydb
, myvims
, rollbackList
)
2548 if isinstance(e
, db_base_Exception
):
2549 error_text
= "database Exception"
2550 elif isinstance(e
, vimconn
.vimconnException
):
2551 error_text
= "VIM Exception"
2553 error_text
= "Exception"
2554 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2555 #logger.error("create_instance: %s", error_text)
2556 raise NfvoException(error_text
, e
.http_code
)
2559 def delete_instance(mydb
, tenant_id
, instance_id
):
2560 #print "Checking that the instance_id exists and getting the instance dictionary"
2561 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2562 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2563 tenant_id
= instanceDict
["tenant_id"]
2564 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2566 #1. Delete from Database
2567 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2576 for sce_vnf
in instanceDict
['vnfs']:
2577 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2578 if datacenter_key
not in myvims
:
2580 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2581 except NfvoException
as e
:
2582 logger
.error(str(e
))
2584 myvim_threads
[datacenter_key
] = myvim_thread
2585 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2586 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2588 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2589 sce_vnf
["datacenter_tenant_id"]))
2590 myvims
[datacenter_key
] = None
2592 myvims
[datacenter_key
] = vims
.values()[0]
2593 myvim
= myvims
[datacenter_key
]
2594 myvim_thread
= myvim_threads
[datacenter_key
]
2595 for vm
in sce_vnf
['vms']:
2597 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2601 if is_task_id(vm
['vim_vm_id']):
2602 task_id
= vm
['vim_vm_id']
2603 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2605 error_msg
+= "\n VM was scheduled for create, but task {} is not found".format(task_id
)
2608 if old_task
["status"] == "enqueued":
2609 old_task
["status"] = "deleted"
2610 elif old_task
["status"] == "error":
2612 elif old_task
["status"] == "processing":
2613 task
= new_task("del-vm", (task_id
, vm
["interfaces"]), depends
={task_id
: old_task
})
2615 task
= new_task("del-vm", (old_task
["result"], vm
["interfaces"]))
2617 task
= new_task("del-vm", (vm
['vim_vm_id'], vm
["interfaces"]) )
2619 myvim_thread
.insert_task(task
)
2620 except vimconn
.vimconnNotFoundException
as e
:
2621 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2622 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2623 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2624 except vimconn
.vimconnException
as e
:
2625 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2626 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2627 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2631 for net
in instanceDict
['nets']:
2632 if not net
['created']:
2633 continue #skip not created nets
2634 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2635 if datacenter_key
not in myvims
:
2637 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2638 except NfvoException
as e
:
2639 logger
.error(str(e
))
2641 myvim_threads
[datacenter_key
] = myvim_thread
2642 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2643 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2645 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2646 myvims
[datacenter_key
] = None
2648 myvims
[datacenter_key
] = vims
.values()[0]
2649 myvim
= myvims
[datacenter_key
]
2650 myvim_thread
= myvim_threads
[datacenter_key
]
2653 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2657 if is_task_id(net
['vim_net_id']):
2658 task_id
= net
['vim_net_id']
2659 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2661 error_msg
+= "\n NET was scheduled for create, but task {} is not found".format(task_id
)
2664 if old_task
["status"] == "enqueued":
2665 old_task
["status"] = "deleted"
2666 elif old_task
["status"] == "error":
2668 elif old_task
["status"] == "processing":
2669 task
= new_task("del-net", task_id
, depends
={task_id
: old_task
})
2671 task
= new_task("del-net", old_task
["result"])
2673 task
= new_task("del-net", (net
['vim_net_id'], net
['sdn_net_id']))
2675 myvim_thread
.insert_task(task
)
2676 except vimconn
.vimconnNotFoundException
as e
:
2677 error_msg
+= "\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2678 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2679 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2680 except vimconn
.vimconnException
as e
:
2681 error_msg
+= "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'],
2682 net
["datacenter_id"],
2683 e
.http_code
, str(e
))
2684 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2685 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2686 if len(error_msg
) > 0:
2687 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2689 return 'instance ' + message
+ ' deleted'
2692 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2693 '''Refreshes a scenario instance. It modifies instanceDict'''
2695 - 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
2698 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2699 # #print "nfvo.refresh_instance begins"
2700 # #print json.dumps(instanceDict, indent=4)
2702 # #print "Getting the VIM URL and the VIM tenant_id"
2705 # # 1. Getting VIM vm and net list
2706 # vms_updated = [] #List of VM instance uuids in openmano that were updated
2709 # for sce_vnf in instanceDict['vnfs']:
2710 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
2711 # if datacenter_key not in vm_list:
2712 # vm_list[datacenter_key] = []
2713 # if datacenter_key not in myvims:
2714 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
2715 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
2716 # if len(vims) == 0:
2717 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
2718 # myvims[datacenter_key] = None
2720 # myvims[datacenter_key] = vims.values()[0]
2721 # for vm in sce_vnf['vms']:
2722 # vm_list[datacenter_key].append(vm['vim_vm_id'])
2723 # vms_notupdated.append(vm["uuid"])
2725 # nets_updated = [] #List of VM instance uuids in openmano that were updated
2726 # nets_notupdated=[]
2728 # for net in instanceDict['nets']:
2729 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
2730 # if datacenter_key not in net_list:
2731 # net_list[datacenter_key] = []
2732 # if datacenter_key not in myvims:
2733 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
2734 # datacenter_tenant_id=net["datacenter_tenant_id"])
2735 # if len(vims) == 0:
2736 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
2737 # myvims[datacenter_key] = None
2739 # myvims[datacenter_key] = vims.values()[0]
2741 # net_list[datacenter_key].append(net['vim_net_id'])
2742 # nets_notupdated.append(net["uuid"])
2744 # # 1. Getting the status of all VMs
2746 # for datacenter_key in myvims:
2747 # if not vm_list.get(datacenter_key):
2751 # if not myvims[datacenter_key]:
2752 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2755 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
2757 # except vimconn.vimconnException as e:
2758 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2759 # failed_message = str(e)
2761 # for vm in vm_list[datacenter_key]:
2762 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2764 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2765 # for sce_vnf in instanceDict['vnfs']:
2766 # for vm in sce_vnf['vms']:
2767 # vm_id = vm['vim_vm_id']
2768 # interfaces = vm_dict[vm_id].pop('interfaces', [])
2769 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2770 # has_mgmt_iface = False
2771 # for iface in vm["interfaces"]:
2772 # if iface["type"]=="mgmt":
2773 # has_mgmt_iface = True
2774 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
2775 # vm_dict[vm_id]['status'] = "ACTIVE"
2776 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
2777 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
2778 # 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'):
2779 # vm['status'] = vm_dict[vm_id]['status']
2780 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
2781 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
2782 # # 2.1. Update in openmano DB the VMs whose status changed
2784 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
2785 # vms_notupdated.remove(vm["uuid"])
2787 # vms_updated.append(vm["uuid"])
2788 # except db_base_Exception as e:
2789 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2790 # # 2.2. Update in openmano DB the interface VMs
2791 # for interface in interfaces:
2792 # #translate from vim_net_id to instance_net_id
2793 # network_id_list=[]
2794 # for net in instanceDict['nets']:
2795 # if net["vim_net_id"] == interface["vim_net_id"]:
2796 # network_id_list.append(net["uuid"])
2797 # if not network_id_list:
2799 # del interface["vim_net_id"]
2801 # for network_id in network_id_list:
2802 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
2803 # except db_base_Exception as e:
2804 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
2806 # # 3. Getting the status of all nets
2808 # for datacenter_key in myvims:
2809 # if not net_list.get(datacenter_key):
2812 # failed_message = ""
2813 # if not myvims[datacenter_key]:
2814 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2817 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
2819 # except vimconn.vimconnException as e:
2820 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2821 # failed_message = str(e)
2823 # for net in net_list[datacenter_key]:
2824 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2826 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2827 # # TODO: update nets inside a vnf
2828 # for net in instanceDict['nets']:
2829 # net_id = net['vim_net_id']
2830 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
2831 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
2832 # 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'):
2833 # net['status'] = net_dict[net_id]['status']
2834 # net['error_msg'] = net_dict[net_id].get('error_msg')
2835 # net['vim_info'] = net_dict[net_id].get('vim_info')
2836 # # 5.1. Update in openmano DB the nets whose status changed
2838 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
2839 # nets_notupdated.remove(net["uuid"])
2841 # nets_updated.append(net["uuid"])
2842 # except db_base_Exception as e:
2843 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2845 # # Returns appropriate output
2846 # #print "nfvo.refresh_instance finishes"
2847 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2848 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
2849 instance_id
= instanceDict
['uuid']
2850 # if len(vms_notupdated)+len(nets_notupdated)>0:
2851 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
2852 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
2854 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2857 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2858 #print "Checking that the instance_id exists and getting the instance dictionary"
2859 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2860 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2862 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2863 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2865 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2866 myvim
= vims
.values()[0]
2869 input_vnfs
= action_dict
.pop("vnfs", [])
2870 input_vms
= action_dict
.pop("vms", [])
2871 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2875 for sce_vnf
in instanceDict
['vnfs']:
2876 for vm
in sce_vnf
['vms']:
2877 if not action_over_all
:
2878 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2879 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2882 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2883 if "console" in action_dict
:
2884 if not global_config
["http_console_proxy"]:
2885 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2886 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2887 protocol
=data
["protocol"],
2888 ip
= data
["server"],
2889 port
= data
["port"],
2890 suffix
= data
["suffix"]),
2894 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2895 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2896 "description": "this console is only reachable by local interface",
2901 #print "console data", data
2903 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2904 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2905 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2906 protocol
=data
["protocol"],
2907 ip
= global_config
["http_console_host"],
2908 port
= console_thread
.port
,
2909 suffix
= data
["suffix"]),
2913 except NfvoException
as e
:
2914 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2918 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2920 except vimconn
.vimconnException
as e
:
2921 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2924 if vm_ok
==0: #all goes wrong
2930 def create_or_use_console_proxy_thread(console_server
, console_port
):
2931 #look for a non-used port
2932 console_thread_key
= console_server
+ ":" + str(console_port
)
2933 if console_thread_key
in global_config
["console_thread"]:
2934 #global_config["console_thread"][console_thread_key].start_timeout()
2935 return global_config
["console_thread"][console_thread_key
]
2937 for port
in global_config
["console_port_iterator"]():
2938 #print "create_or_use_console_proxy_thread() port:", port
2939 if port
in global_config
["console_ports"]:
2942 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2944 global_config
["console_thread"][console_thread_key
] = clithread
2945 global_config
["console_ports"][port
] = console_thread_key
2947 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2948 #port used, try with onoher
2950 except cli
.ConsoleProxyException
as e
:
2951 raise NfvoException(str(e
), HTTP_Bad_Request
)
2952 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2955 def check_tenant(mydb
, tenant_id
):
2956 '''check that tenant exists at database'''
2957 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2959 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2963 def new_tenant(mydb
, tenant_dict
):
2964 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2968 def delete_tenant(mydb
, tenant
):
2969 #get nfvo_tenant info
2971 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2972 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2973 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2976 def new_datacenter(mydb
, datacenter_descriptor
):
2977 if "config" in datacenter_descriptor
:
2978 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2979 #Check that datacenter-type is correct
2980 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2983 module
= "vimconn_" + datacenter_type
2984 pkg
= __import__("osm_ro." + module
)
2985 vim_conn
= getattr(pkg
, module
)
2986 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
2987 except (IOError, ImportError):
2988 # if module_info and module_info[0]:
2989 # file.close(module_info[0])
2990 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2992 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2993 return datacenter_id
2996 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2997 # obtain data, check that only one exist
2998 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
3001 datacenter_id
= datacenter
['uuid']
3002 where
={'uuid': datacenter
['uuid']}
3003 remove_port_mapping
= False
3004 if "config" in datacenter_descriptor
:
3005 if datacenter_descriptor
['config'] != None:
3007 new_config_dict
= datacenter_descriptor
["config"]
3010 for k
in new_config_dict
:
3011 if new_config_dict
[k
] == None:
3013 if k
== 'sdn-controller':
3014 remove_port_mapping
= True
3016 config_text
= datacenter
.get("config")
3019 config_dict
= yaml
.load(config_text
)
3020 config_dict
.update(new_config_dict
)
3024 except Exception as e
:
3025 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
3027 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
3029 datacenter_descriptor
["config"] = None
3030 if remove_port_mapping
:
3032 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
3033 except ovimException
as e
:
3034 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
3036 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
3037 return datacenter_id
3040 def delete_datacenter(mydb
, datacenter
):
3041 #get nfvo_tenant info
3042 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
3043 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
3045 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
3046 except ovimException
as e
:
3047 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
3048 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
3051 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):
3052 #get datacenter info
3053 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
, vim_passwd
=vim_password
)
3054 datacenter_name
= myvim
["name"]
3056 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
3058 # get nfvo_tenant info
3059 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
3060 if vim_tenant_name
==None:
3061 vim_tenant_name
=tenant_dict
['name']
3063 #check that this association does not exist before
3064 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
3065 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3066 if len(tenants_datacenters
)>0:
3067 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
3069 vim_tenant_id_exist_atdb
=False
3070 if not create_vim_tenant
:
3071 where_
={"datacenter_id": datacenter_id
}
3072 if vim_tenant_id
!=None:
3073 where_
["vim_tenant_id"] = vim_tenant_id
3074 if vim_tenant_name
!=None:
3075 where_
["vim_tenant_name"] = vim_tenant_name
3076 #check if vim_tenant_id is already at database
3077 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
3078 if len(datacenter_tenants_dict
)>=1:
3079 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
3080 vim_tenant_id_exist_atdb
=True
3081 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
3083 datacenter_tenants_dict
= {}
3084 #insert at table datacenter_tenants
3085 else: #if vim_tenant_id==None:
3086 #create tenant at VIM if not provided
3088 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
3089 except vimconn
.vimconnException
as e
:
3090 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
3091 datacenter_tenants_dict
= {}
3092 datacenter_tenants_dict
["created"]="true"
3094 #fill datacenter_tenants table
3095 if not vim_tenant_id_exist_atdb
:
3096 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
3097 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
3098 datacenter_tenants_dict
["user"] = vim_username
3099 datacenter_tenants_dict
["passwd"] = vim_password
3100 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
3102 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
3103 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
3104 datacenter_tenants_dict
["uuid"] = id_
3106 #fill tenants_datacenters table
3107 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
3108 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
3109 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
3111 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
3112 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
3113 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
3114 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
3116 thread_id
= datacenter_tenants_dict
["uuid"]
3117 vim_threads
["running"][thread_id
] = new_thread
3118 return datacenter_id
3121 def edit_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=None, vim_tenant_name
=None,
3122 vim_username
=None, vim_password
=None, config
=None):
3123 #Obtain the data of this datacenter_tenant_id
3124 vim_data
= mydb
.get_rows(
3125 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
3126 "datacenter_tenants.passwd", "datacenter_tenants.config"),
3127 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
3128 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
3129 "tenants_datacenters.datacenter_id": datacenter_id
})
3131 logger
.debug(str(vim_data
))
3132 if len(vim_data
) < 1:
3133 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
3137 v
['config'] = yaml
.load(v
['config'])
3140 v
['vim_tenant_id'] = vim_tenant_id
3142 v
['vim_tenant_name'] = vim_tenant_name
3144 v
['user'] = vim_username
3146 v
['passwd'] = vim_password
3150 v
['config'].update(config
)
3152 logger
.debug(str(v
))
3153 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
3154 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
3155 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
3157 return datacenter_id
3159 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
3160 #get datacenter info
3161 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
3163 #get nfvo_tenant info
3164 if not tenant_id
or tenant_id
=="any":
3167 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
3168 tenant_uuid
= tenant_dict
['uuid']
3170 #check that this association exist before
3171 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
3173 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
3174 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3175 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
3176 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
3178 #delete this association
3179 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3181 #get vim_tenant info and deletes
3183 for tenant_datacenter_item
in tenant_datacenter_list
:
3184 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
3185 #try to delete vim:tenant
3187 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
3188 if vim_tenant_dict
['created']=='true':
3189 #delete tenant at VIM if created by NFVO
3191 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
3192 except vimconn
.vimconnException
as e
:
3193 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
3194 logger
.warn(warning
)
3195 except db_base_Exception
as e
:
3196 logger
.error("Cannot delete datacenter_tenants " + str(e
))
3197 pass # the error will be caused because dependencies, vim_tenant can not be deleted
3198 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
3199 thread
= vim_threads
["running"][thread_id
]
3200 thread
.insert_task(new_task("exit", None))
3201 vim_threads
["deleting"][thread_id
] = thread
3202 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
3205 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
3207 #get datacenter info
3208 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3210 if 'net-update' in action_dict
:
3212 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
3214 except vimconn
.vimconnException
as e
:
3215 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
3216 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3217 #update nets Change from VIM format to NFVO format
3220 net_nfvo
={'datacenter_id': datacenter_id
}
3221 net_nfvo
['name'] = net
['name']
3222 #net_nfvo['description']= net['name']
3223 net_nfvo
['vim_net_id'] = net
['id']
3224 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3225 net_nfvo
['shared'] = net
['shared']
3226 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3227 net_list
.append(net_nfvo
)
3228 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
3229 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
3231 elif 'net-edit' in action_dict
:
3232 net
= action_dict
['net-edit'].pop('net')
3233 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3234 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
3235 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3237 elif 'net-delete' in action_dict
:
3238 net
= action_dict
['net-deelte'].get('net')
3239 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3240 result
= mydb
.delete_row(FROM
='datacenter_nets',
3241 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3245 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
3248 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
3249 #get datacenter info
3250 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3252 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
3253 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
3254 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
3258 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
3259 #get datacenter info
3260 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3263 action_dict
= action_dict
["netmap"]
3264 if 'vim_id' in action_dict
:
3265 filter_dict
["id"] = action_dict
['vim_id']
3266 if 'vim_name' in action_dict
:
3267 filter_dict
["name"] = action_dict
['vim_name']
3269 filter_dict
["shared"] = True
3272 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
3273 except vimconn
.vimconnException
as e
:
3274 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
3275 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3276 if len(vim_nets
)>1 and action_dict
:
3277 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
3278 elif len(vim_nets
)==0: # and action_dict:
3279 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
3281 for net
in vim_nets
:
3282 net_nfvo
={'datacenter_id': datacenter_id
}
3283 if action_dict
and "name" in action_dict
:
3284 net_nfvo
['name'] = action_dict
['name']
3286 net_nfvo
['name'] = net
['name']
3287 #net_nfvo['description']= net['name']
3288 net_nfvo
['vim_net_id'] = net
['id']
3289 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3290 net_nfvo
['shared'] = net
['shared']
3291 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3293 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
3294 net_nfvo
["status"] = "OK"
3295 net_nfvo
["uuid"] = net_id
3296 except db_base_Exception
as e
:
3300 net_nfvo
["status"] = "FAIL: " + str(e
)
3301 net_list
.append(net_nfvo
)
3304 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
3305 # obtain all network data
3307 if utils
.check_valid_uuid(network_id
):
3308 filter_dict
= {"id": network_id
}
3310 filter_dict
= {"name": network_id
}
3312 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3313 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
3314 except vimconn
.vimconnException
as e
:
3315 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
3316 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
3318 # ensure the network is defined
3319 if len(network
) == 0:
3320 raise NfvoException("Network {} is not present in the system".format(network_id
),
3323 # ensure there is only one network with the provided name
3324 if len(network
) > 1:
3325 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), HTTP_Bad_Request
)
3327 # ensure it is a dataplane network
3328 if network
[0]['type'] != 'data':
3331 # ensure we use the id
3332 network_id
= network
[0]['id']
3334 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
3335 # and with instance_scenario_id==NULL
3336 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
3337 search_dict
= {'vim_net_id': network_id
}
3340 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
3341 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
3342 except db_base_Exception
as e
:
3343 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
3344 network_id
) + str(e
), HTTP_Internal_Server_Error
)
3348 if net
['sdn_net_id'] != None:
3350 sdn_net_id
= net
['sdn_net_id']
3352 if sdn_net_counter
== 0:
3354 elif sdn_net_counter
== 1:
3357 raise NfvoException("More than one SDN network is associated to vim network {}".format(
3358 network_id
), HTTP_Internal_Server_Error
)
3360 def get_sdn_controller_id(mydb
, datacenter
):
3361 # Obtain sdn controller id
3362 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
3366 return yaml
.load(config
).get('sdn-controller')
3368 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
3370 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
3371 if not sdn_network_id
:
3372 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), HTTP_Internal_Server_Error
)
3374 #Obtain sdn controller id
3375 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
3376 if not controller_id
:
3377 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), HTTP_Internal_Server_Error
)
3379 #Obtain sdn controller info
3380 sdn_controller
= ovim
.show_of_controller(controller_id
)
3383 'name': 'external_port',
3384 'net_id': sdn_network_id
,
3385 'ofc_id': controller_id
,
3386 'switch_dpid': sdn_controller
['dpid'],
3387 'switch_port': descriptor
['port']
3390 if 'vlan' in descriptor
:
3391 port_data
['vlan'] = descriptor
['vlan']
3392 if 'mac' in descriptor
:
3393 port_data
['mac'] = descriptor
['mac']
3395 result
= ovim
.new_port(port_data
)
3396 except ovimException
as e
:
3397 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
3398 sdn_network_id
, network_id
) + str(e
), HTTP_Internal_Server_Error
)
3399 except db_base_Exception
as e
:
3400 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
3401 network_id
) + str(e
), HTTP_Internal_Server_Error
)
3403 return 'Port uuid: '+ result
3405 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
3407 filter = {'uuid': port_id
}
3409 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
3410 if not sdn_network_id
:
3411 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
3412 HTTP_Internal_Server_Error
)
3413 #in case no port_id is specified only ports marked as 'external_port' will be detached
3414 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
3417 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
3418 except ovimException
as e
:
3419 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
3420 HTTP_Internal_Server_Error
)
3422 if len(port_list
) == 0:
3423 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
3427 for port
in port_list
:
3429 port_uuid_list
.append(port
['uuid'])
3430 ovim
.delete_port(port
['uuid'])
3431 except ovimException
as e
:
3432 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), HTTP_Internal_Server_Error
)
3434 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
3436 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
3437 #get datacenter info
3438 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3441 if utils
.check_valid_uuid(name
):
3442 filter_dict
["id"] = name
3444 filter_dict
["name"] = name
3446 if item
=="networks":
3447 #filter_dict['tenant_id'] = myvim['tenant_id']
3448 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
3450 if len(content
) == 0:
3451 raise NfvoException("Network {} is not present in the system. ".format(name
),
3454 #Update the networks with the attached ports
3456 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
3457 if sdn_network_id
!= None:
3459 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
3460 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
3461 except ovimException
as e
:
3462 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), HTTP_Internal_Server_Error
)
3463 #Remove field name and if port name is external_port save it as 'type'
3464 for port
in port_list
:
3465 if port
['name'] == 'external_port':
3466 port
['type'] = "External"
3468 net
['sdn_network_id'] = sdn_network_id
3469 net
['sdn_attached_ports'] = port_list
3471 elif item
=="tenants":
3472 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
3473 elif item
== "images":
3475 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
3477 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3478 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
3479 if name
and len(content
)==1:
3480 return {item
[:-1]: content
[0]}
3481 elif name
and len(content
)==0:
3482 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
3485 return {item
: content
}
3486 except vimconn
.vimconnException
as e
:
3487 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
3488 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
3491 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
3492 #get datacenter info
3493 if tenant_id
== "any":
3496 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3498 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
3499 logger
.debug("vim_action_delete vim response: " + str(content
))
3500 items
= content
.values()[0]
3501 if type(items
)==list and len(items
)==0:
3502 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
3503 elif type(items
)==list and len(items
)>1:
3504 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
3505 else: # it is a dict
3506 item_id
= items
["id"]
3507 item_name
= str(items
.get("name"))
3510 if item
=="networks":
3511 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
3512 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
3513 if sdn_network_id
!= None:
3514 #Delete any port attachment to this network
3516 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
3517 except ovimException
as e
:
3518 raise NfvoException(
3519 "ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
3520 HTTP_Internal_Server_Error
)
3522 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
3523 for port
in port_list
:
3524 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
3526 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
3528 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id
, 'vim_net_id': item_id
})
3529 except db_base_Exception
as e
:
3530 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
3531 str(e
), HTTP_Internal_Server_Error
)
3533 #Delete the SDN network
3535 ovim
.delete_network(sdn_network_id
)
3536 except ovimException
as e
:
3537 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
3538 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
3539 HTTP_Internal_Server_Error
)
3541 content
= myvim
.delete_network(item_id
)
3542 elif item
=="tenants":
3543 content
= myvim
.delete_tenant(item_id
)
3544 elif item
== "images":
3545 content
= myvim
.delete_image(item_id
)
3547 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3548 except vimconn
.vimconnException
as e
:
3549 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
3550 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
3552 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
3555 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
3556 #get datacenter info
3557 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
3558 if tenant_id
== "any":
3560 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3562 if item
=="networks":
3563 net
= descriptor
["network"]
3564 net_name
= net
.pop("name")
3565 net_type
= net
.pop("type", "bridge")
3566 net_public
= net
.pop("shared", False)
3567 net_ipprofile
= net
.pop("ip_profile", None)
3568 net_vlan
= net
.pop("vlan", None)
3569 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
3571 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
3572 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
3575 sdn_network
['vlan'] = net_vlan
3576 sdn_network
['type'] = net_type
3577 sdn_network
['name'] = net_name
3578 ovim_content
= ovim
.new_network(sdn_network
)
3579 except ovimException
as e
:
3580 self
.logger
.error("ovimException creating SDN network={} ".format(
3581 sdn_network
) + str(e
), exc_info
=True)
3582 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
3583 HTTP_Internal_Server_Error
)
3585 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
3586 # use instance_scenario_id=None to distinguish from real instaces of nets
3587 correspondence
= {'instance_scenario_id': None, 'sdn_net_id': ovim_content
, 'vim_net_id': content
}
3588 #obtain datacenter_tenant_id
3589 correspondence
['datacenter_tenant_id'] = mydb
.get_rows(SELECT
=('uuid',), FROM
='datacenter_tenants', WHERE
={'datacenter_id': datacenter
})[0]['uuid']
3592 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
3593 except db_base_Exception
as e
:
3594 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
3595 str(e
), HTTP_Internal_Server_Error
)
3596 elif item
=="tenants":
3597 tenant
= descriptor
["tenant"]
3598 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
3600 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3601 except vimconn
.vimconnException
as e
:
3602 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
3604 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
3606 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
3607 data
= ovim
.new_of_controller(sdn_controller
)
3608 logger
.debug('New SDN controller created with uuid {}'.format(data
))
3611 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
3612 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
3613 msg
= 'SDN controller {} updated'.format(data
)
3617 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
3618 if controller_id
== None:
3619 data
= ovim
.get_of_controllers()
3621 data
= ovim
.show_of_controller(controller_id
)
3623 msg
= 'SDN controller list:\n {}'.format(data
)
3627 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
3628 select_
= ('uuid', 'config')
3629 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
3630 for datacenter
in datacenters
:
3631 if datacenter
['config']:
3632 config
= yaml
.load(datacenter
['config'])
3633 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
3634 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
3636 data
= ovim
.delete_of_controller(controller_id
)
3637 msg
= 'SDN controller {} deleted'.format(data
)
3641 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
3642 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
3643 if len(controller
) < 1:
3644 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
3647 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
3649 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
3651 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
3652 switch_dpid
= sdn_controller
["dpid"]
3655 for compute_node
in sdn_port_mapping
:
3656 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
3658 element
["compute_node"] = compute_node
["compute_node"]
3659 for port
in compute_node
["ports"]:
3660 element
["pci"] = port
.get("pci")
3661 element
["switch_port"] = port
.get("switch_port")
3662 element
["switch_mac"] = port
.get("switch_mac")
3663 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
3664 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
3665 " or 'switch_mac'", HTTP_Bad_Request
)
3666 maps
.append(dict(element
))
3668 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
3670 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
3671 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
3674 "sdn-controller": None,
3675 "datacenter-id": datacenter_id
,
3677 "ports_mapping": list()
3680 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
3681 if datacenter
['config']:
3682 config
= yaml
.load(datacenter
['config'])
3683 if 'sdn-controller' in config
:
3684 controller_id
= config
['sdn-controller']
3685 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
3686 result
["sdn-controller"] = controller_id
3687 result
["dpid"] = sdn_controller
["dpid"]
3689 if result
["sdn-controller"] == None:
3690 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), HTTP_Bad_Request
)
3691 if result
["dpid"] == None:
3692 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
3693 HTTP_Internal_Server_Error
)
3698 ports_correspondence_dict
= dict()
3700 if result
["sdn-controller"] != link
["ofc_id"]:
3701 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
3702 if result
["dpid"] != link
["switch_dpid"]:
3703 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
3705 element
["pci"] = link
["pci"]
3706 if link
["switch_port"]:
3707 element
["switch_port"] = link
["switch_port"]
3708 if link
["switch_mac"]:
3709 element
["switch_mac"] = link
["switch_mac"]
3711 if not link
["compute_node"] in ports_correspondence_dict
:
3713 content
["compute_node"] = link
["compute_node"]
3714 content
["ports"] = list()
3715 ports_correspondence_dict
[link
["compute_node"]] = content
3717 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
3719 for key
in sorted(ports_correspondence_dict
):
3720 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
3724 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
3725 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})