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"):
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 if cloud_config
and cloud_config
.get("user-data") != None:
1896 new_cloud_config
["user-data"] = cloud_config
["user-data"]
1897 if cloud_config_preserve
and cloud_config_preserve
.get("user-data") != None:
1898 new_cloud_config
["user-data"] = cloud_config_preserve
["user-data"]
1901 new_cloud_config
["config-files"] = []
1902 if cloud_config
and cloud_config
.get("config-files") != None:
1903 new_cloud_config
["config-files"] += cloud_config
["config-files"]
1904 if cloud_config_preserve
:
1905 for file in cloud_config_preserve
.get("config-files", ()):
1906 for index
in range(0, len(new_cloud_config
["config-files"])):
1907 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
1908 new_cloud_config
["config-files"][index
] = file
1911 new_cloud_config
["config-files"].append(file)
1912 if not new_cloud_config
["config-files"]:
1913 del new_cloud_config
["config-files"]
1914 return new_cloud_config
1917 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
1918 datacenter_id
= None
1919 datacenter_name
= None
1922 if datacenter_tenant_id
:
1923 thread_id
= datacenter_tenant_id
1924 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
1926 where_
={"td.nfvo_tenant_id": tenant_id
}
1927 if datacenter_id_name
:
1928 if utils
.check_valid_uuid(datacenter_id_name
):
1929 datacenter_id
= datacenter_id_name
1930 where_
["dt.datacenter_id"] = datacenter_id
1932 datacenter_name
= datacenter_id_name
1933 where_
["d.name"] = datacenter_name
1934 if datacenter_tenant_id
:
1935 where_
["dt.uuid"] = datacenter_tenant_id
1936 datacenters
= mydb
.get_rows(
1937 SELECT
=("dt.uuid as datacenter_tenant_id",),
1938 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
1939 "join datacenters as d on d.uuid=dt.datacenter_id",
1941 if len(datacenters
) > 1:
1942 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1944 thread_id
= datacenters
[0]["datacenter_tenant_id"]
1945 thread
= vim_threads
["running"].get(thread_id
)
1947 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1948 return thread_id
, thread
1949 except db_base_Exception
as e
:
1950 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
1953 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1954 datacenter_id
= None
1955 datacenter_name
= None
1956 if datacenter_id_name
:
1957 if utils
.check_valid_uuid(datacenter_id_name
):
1958 datacenter_id
= datacenter_id_name
1960 datacenter_name
= datacenter_id_name
1961 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1963 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1965 #print "nfvo.datacenter_action() error. Several datacenters found"
1966 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1967 return vims
.keys()[0], vims
.values()[0]
1971 '''Takes dict d and updates it with the values in dict u.'''
1972 '''It merges all depth levels'''
1973 for k
, v
in u
.iteritems():
1974 if isinstance(v
, collections
.Mapping
):
1975 r
= update(d
.get(k
, {}), v
)
1982 def create_instance(mydb
, tenant_id
, instance_dict
):
1983 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1984 # logger.debug("Creating instance...")
1985 scenario
= instance_dict
["scenario"]
1987 #find main datacenter
1989 myvim_threads_id
= {}
1992 datacenter
= instance_dict
.get("datacenter")
1993 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1994 myvims
[default_datacenter_id
] = vim
1995 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
1996 tasks_to_launch
[myvim_threads_id
[default_datacenter_id
]] = []
1997 #myvim_tenant = myvim['tenant_id']
1998 # default_datacenter_name = vim['name']
2001 #print "Checking that the scenario exists and getting the scenario dictionary"
2002 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
2004 #logger.debug(">>>>>>> Dictionaries before merging")
2005 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
2006 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
2009 instance_name
= instance_dict
["name"]
2010 instance_uuid
= str(uuid4())
2011 uuid_list
.append(instance_uuid
)
2012 db_instance_scenario
= {
2013 "uuid": instance_uuid
,
2014 "name": instance_name
,
2015 "tenant_id": tenant_id
,
2016 "scenario_id": scenarioDict
['uuid'],
2017 "datacenter_id": default_datacenter_id
,
2018 # filled bellow 'datacenter_tenant_id'
2019 "description": instance_dict
.get("description"),
2022 if scenarioDict
.get("cloud-config"):
2023 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
2024 default_flow_style
=True, width
=256)
2026 vnf_net2instance
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2027 sce_net2instance
= {}
2028 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2029 auxNetDict
['scenario'] = {}
2031 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
2033 # 0 check correct parameters
2034 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2036 for scenario_net
in scenarioDict
['nets']:
2037 if net_name
== scenario_net
["name"]:
2041 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
2042 if "sites" not in net_instance_desc
:
2043 net_instance_desc
["sites"] = [ {} ]
2044 site_without_datacenter_field
= False
2045 for site
in net_instance_desc
["sites"]:
2046 if site
.get("datacenter"):
2047 if site
["datacenter"] not in myvims
:
2048 #Add this datacenter to myvims
2049 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
2051 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
2052 tasks_to_launch
[myvim_threads_id
[d
]] = []
2053 site
["datacenter"] = d
#change name to id
2055 if site_without_datacenter_field
:
2056 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
2057 site_without_datacenter_field
= True
2058 site
["datacenter"] = default_datacenter_id
#change name to id
2060 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
2062 for scenario_vnf
in scenarioDict
['vnfs']:
2063 if vnf_name
== scenario_vnf
['name']:
2067 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
2068 if "datacenter" in vnf_instance_desc
:
2069 # Add this datacenter to myvims
2070 if vnf_instance_desc
["datacenter"] not in myvims
:
2071 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2073 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2074 tasks_to_launch
[myvim_threads_id
[d
]] = []
2075 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2077 #0.1 parse cloud-config parameters
2078 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2080 #0.2 merge instance information into scenario
2081 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2082 #However, this is not possible yet.
2083 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2084 for scenario_net
in scenarioDict
['nets']:
2085 if net_name
== scenario_net
["name"]:
2086 if 'ip-profile' in net_instance_desc
:
2087 # translate from input format to database format
2088 ipprofile_in
= net_instance_desc
['ip-profile']
2090 ipprofile_db
['subnet_address'] = ipprofile_in
.get('subnet-address')
2091 ipprofile_db
['ip_version'] = ipprofile_in
.get('ip-version', 'IPv4')
2092 ipprofile_db
['gateway_address'] = ipprofile_in
.get('gateway-address')
2093 ipprofile_db
['dns_address'] = ipprofile_in
.get('dns-address')
2094 if isinstance(ipprofile_db
['dns_address'], (list, tuple)):
2095 ipprofile_db
['dns_address'] = ";".join(ipprofile_db
['dns_address'])
2096 if 'dhcp' in ipprofile_in
:
2097 ipprofile_db
['dhcp_start_address'] = ipprofile_in
['dhcp'].get('start-address')
2098 ipprofile_db
['dhcp_enabled'] = ipprofile_in
['dhcp'].get('enabled', True)
2099 ipprofile_db
['dhcp_count'] = ipprofile_in
['dhcp'].get('count' )
2100 if 'ip_profile' not in scenario_net
:
2101 scenario_net
['ip_profile'] = ipprofile_db
2103 update(scenario_net
['ip_profile'], ipprofile_db
)
2104 for interface
in net_instance_desc
.get('interfaces', () ):
2105 if 'ip_address' in interface
:
2106 for vnf
in scenarioDict
['vnfs']:
2107 if interface
['vnf'] == vnf
['name']:
2108 for vnf_interface
in vnf
['interfaces']:
2109 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2110 vnf_interface
['ip_address']=interface
['ip_address']
2112 #logger.debug(">>>>>>>> Merged dictionary")
2113 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
2115 # 1. Creating new nets (sce_nets) in the VIM"
2116 db_instance_nets
= []
2117 for sce_net
in scenarioDict
['nets']:
2118 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
2119 net_name
= descriptor_net
.get("vim-network-name")
2120 sce_net2instance
[sce_net
['uuid']] = {}
2121 auxNetDict
['scenario'][sce_net
['uuid']] = {}
2123 sites
= descriptor_net
.get("sites", [ {} ])
2125 if site
.get("datacenter"):
2126 vim
= myvims
[ site
["datacenter"] ]
2127 datacenter_id
= site
["datacenter"]
2128 myvim_thread_id
= myvim_threads_id
[ site
["datacenter"] ]
2130 vim
= myvims
[ default_datacenter_id
]
2131 datacenter_id
= default_datacenter_id
2132 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2133 net_type
= sce_net
['type']
2134 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
2135 if sce_net
["external"]:
2137 net_name
= sce_net
["name"]
2138 if "netmap-use" in site
or "netmap-create" in site
:
2139 create_network
= False
2140 lookfor_network
= False
2141 if "netmap-use" in site
:
2142 lookfor_network
= True
2143 if utils
.check_valid_uuid(site
["netmap-use"]):
2144 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2145 lookfor_filter
["id"] = site
["netmap-use"]
2147 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2148 lookfor_filter
["name"] = site
["netmap-use"]
2149 if "netmap-create" in site
:
2150 create_network
= True
2151 net_vim_name
= net_name
2152 if site
["netmap-create"]:
2153 net_vim_name
= site
["netmap-create"]
2155 elif sce_net
['vim_id'] != None:
2156 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
2157 create_network
= False
2158 lookfor_network
= True
2159 lookfor_filter
["id"] = sce_net
['vim_id']
2160 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
2161 #look for network at datacenter and return error
2163 #There is not a netmap, look at datacenter for a net with this name and create if not found
2164 create_network
= True
2165 lookfor_network
= True
2166 lookfor_filter
["name"] = sce_net
["name"]
2167 net_vim_name
= sce_net
["name"]
2168 filter_text
= "scenario name '%s'" % sce_net
["name"]
2171 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
2172 net_name
= net_name
[:255] #limit length
2173 net_vim_name
= net_name
2174 create_network
= True
2175 lookfor_network
= False
2178 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
2179 if len(vim_nets
) > 1:
2180 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2181 elif len(vim_nets
) == 0:
2182 if not create_network
:
2183 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2185 vim_id
= vim_nets
[0]['id']
2186 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
2187 create_network
= False
2189 #if network is not external
2190 task
= new_task("new-net", (net_vim_name
, net_type
, sce_net
.get('ip_profile',None)))
2191 task_id
= task
["id"]
2192 instance_tasks
[task_id
] = task
2193 tasks_to_launch
[myvim_thread_id
].append(task
)
2194 #network_id = vim.new_network(net_vim_name, net_type, sce_net.get('ip_profile',None))
2196 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = task_id
2197 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':task_id
})
2198 sce_net
["created"] = True
2200 # fill database content
2201 net_uuid
= str(uuid4())
2202 uuid_list
.append(net_uuid
)
2203 sce_net2instance
[sce_net
['uuid']][datacenter_id
] = net_uuid
2206 'vim_net_id': vim_id
,
2207 "instance_scenario_id": instance_uuid
,
2208 "sce_net_id": sce_net
["uuid"],
2209 "created": create_network
,
2210 'datacenter_id': datacenter_id
,
2211 'datacenter_tenant_id': myvim_thread_id
,
2212 'status': 'BUILD' if create_network
else "ACTIVE"
2214 db_instance_nets
.append(db_net
)
2215 if 'ip_profile' in sce_net
:
2217 'instance_net_id': net_uuid
,
2218 'ip_version': sce_net
['ip_profile']['ip_version'],
2219 'subnet_address': sce_net
['ip_profile']['subnet_address'],
2220 'gateway_address': sce_net
['ip_profile']['gateway_address'],
2221 'dns_address': sce_net
['ip_profile']['dns_address'],
2222 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
2223 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
2224 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
2226 db_ip_profiles
.append(db_ip_profile
)
2228 # 2. Creating new nets (vnf internal nets) in the VIM"
2229 # For each vnf net, we create it and we add it to instanceNetlist.
2230 for sce_vnf
in scenarioDict
['vnfs']:
2231 for net
in sce_vnf
['nets']:
2232 if sce_vnf
.get("datacenter"):
2233 vim
= myvims
[ sce_vnf
["datacenter"] ]
2234 datacenter_id
= sce_vnf
["datacenter"]
2235 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"]]
2237 vim
= myvims
[ default_datacenter_id
]
2238 datacenter_id
= default_datacenter_id
2239 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2240 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
2241 net_name
= descriptor_net
.get("name")
2243 net_name
= "%s.%s" %(instance_name
, net
["name"])
2244 net_name
= net_name
[:255] #limit length
2245 net_type
= net
['type']
2246 task
= new_task("new-net", (net_name
, net_type
, net
.get('ip_profile',None)))
2247 task_id
= task
["id"]
2248 instance_tasks
[task_id
] = task
2249 tasks_to_launch
[myvim_thread_id
].append(task
)
2250 # network_id = vim.new_network(net_name, net_type, net.get('ip_profile',None))
2252 if sce_vnf
['uuid'] not in vnf_net2instance
:
2253 vnf_net2instance
[sce_vnf
['uuid']] = {}
2254 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = task_id
2255 if sce_vnf
['uuid'] not in auxNetDict
:
2256 auxNetDict
[sce_vnf
['uuid']] = {}
2257 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = task_id
2258 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':task_id
})
2259 net
["created"] = True
2261 # fill database content
2262 net_uuid
= str(uuid4())
2263 uuid_list
.append(net_uuid
)
2264 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
2267 'vim_net_id': vim_id
,
2268 "instance_scenario_id": instance_uuid
,
2269 "net_id": net
["uuid"],
2271 'datacenter_id': datacenter_id
,
2272 'datacenter_tenant_id': myvim_thread_id
,
2274 db_instance_nets
.append(db_net
)
2275 if 'ip_profile' in net
:
2277 'instance_net_id': net_uuid
,
2278 'ip_version': net
['ip_profile']['ip_version'],
2279 'subnet_address': net
['ip_profile']['subnet_address'],
2280 'gateway_address': net
['ip_profile']['gateway_address'],
2281 'dns_address': net
['ip_profile']['dns_address'],
2282 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
2283 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
2284 'dhcp_count': net
['ip_profile']['dhcp_count'],
2286 db_ip_profiles
.append(db_ip_profile
)
2288 #print "vnf_net2instance:"
2289 #print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
2291 # 3. Creating new vm instances in the VIM
2292 db_instance_vnfs
= []
2293 db_instance_vms
= []
2294 db_instance_interfaces
= []
2295 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2296 sce_vnf_list
= sorted(scenarioDict
['vnfs'], key
=lambda k
: k
['name'])
2297 #for sce_vnf in scenarioDict['vnfs']:
2298 for sce_vnf
in sce_vnf_list
:
2299 vnf_availability_zones
= []
2300 for vm
in sce_vnf
['vms']:
2301 vm_av
= vm
.get('availability_zone')
2302 if vm_av
and vm_av
not in vnf_availability_zones
:
2303 vnf_availability_zones
.append(vm_av
)
2305 # check if there is enough availability zones available at vim level.
2306 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2307 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2308 raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request
)
2310 if sce_vnf
.get("datacenter"):
2311 vim
= myvims
[ sce_vnf
["datacenter"] ]
2312 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"] ]
2313 datacenter_id
= sce_vnf
["datacenter"]
2315 vim
= myvims
[ default_datacenter_id
]
2316 myvim_thread_id
= myvim_threads_id
[ default_datacenter_id
]
2317 datacenter_id
= default_datacenter_id
2318 sce_vnf
["datacenter_id"] = datacenter_id
2321 vnf_uuid
= str(uuid4())
2322 uuid_list
.append(vnf_uuid
)
2325 'instance_scenario_id': instance_uuid
,
2326 'vnf_id': sce_vnf
['vnf_id'],
2327 'sce_vnf_id': sce_vnf
['uuid'],
2328 'datacenter_id': datacenter_id
,
2329 'datacenter_tenant_id': myvim_thread_id
,
2331 db_instance_vnfs
.append(db_instance_vnf
)
2333 for vm
in sce_vnf
['vms']:
2335 myVMDict
['name'] = "{}.{}.{}".format(instance_name
[:64], sce_vnf
['name'][:64], vm
["name"][:64])
2336 myVMDict
['description'] = myVMDict
['name'][0:99]
2338 # myVMDict['start'] = "no"
2339 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2340 #create image at vim in case it not exist
2341 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2342 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2343 vm
['vim_image_id'] = image_id
2345 #create flavor at vim in case it not exist
2346 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2347 if flavor_dict
['extended']!=None:
2348 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2349 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
2351 #Obtain information for additional disks
2352 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
2353 if not extended_flavor_dict
:
2354 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
2357 #extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
2358 myVMDict
['disks'] = None
2359 extended_info
= extended_flavor_dict
[0]['extended']
2360 if extended_info
!= None:
2361 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
2362 if 'disks' in extended_flavor_dict_yaml
:
2363 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
2365 vm
['vim_flavor_id'] = flavor_id
2366 myVMDict
['imageRef'] = vm
['vim_image_id']
2367 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2368 myVMDict
['availability_zone'] = vm
.get('availability_zone')
2369 myVMDict
['networks'] = []
2371 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
2373 for iface
in vm
['interfaces']:
2375 if iface
['type']=="data":
2376 netDict
['type'] = iface
['model']
2377 elif "model" in iface
and iface
["model"]!=None:
2378 netDict
['model']=iface
['model']
2379 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2380 #discover type of interface looking at flavor
2381 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2382 for flavor_iface
in numa
.get('interfaces',[]):
2383 if flavor_iface
.get('name') == iface
['internal_name']:
2384 if flavor_iface
['dedicated'] == 'yes':
2385 netDict
['type']="PF" #passthrough
2386 elif flavor_iface
['dedicated'] == 'no':
2387 netDict
['type']="VF" #siov
2388 elif flavor_iface
['dedicated'] == 'yes:sriov':
2389 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2390 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2392 netDict
["use"]=iface
['type']
2393 if netDict
["use"]=="data" and not netDict
.get("type"):
2394 #print "netDict", netDict
2395 #print "iface", iface
2396 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'])
2397 if flavor_dict
.get('extended')==None:
2398 raise NfvoException(e_text
+ "After database migration some information is not available. \
2399 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2401 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2402 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2403 netDict
["type"]="virtual"
2404 if "vpci" in iface
and iface
["vpci"] is not None:
2405 netDict
['vpci'] = iface
['vpci']
2406 if "mac" in iface
and iface
["mac"] is not None:
2407 netDict
['mac_address'] = iface
['mac']
2408 if "port-security" in iface
and iface
["port-security"] is not None:
2409 netDict
['port_security'] = iface
['port-security']
2410 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2411 netDict
['floating_ip'] = iface
['floating-ip']
2412 netDict
['name'] = iface
['internal_name']
2413 if iface
['net_id'] is None:
2414 for vnf_iface
in sce_vnf
["interfaces"]:
2417 if vnf_iface
['interface_id']==iface
['uuid']:
2418 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
2419 instance_net_id
= sce_net2instance
[ vnf_iface
['sce_net_id'] ][datacenter_id
]
2422 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2423 instance_net_id
= vnf_net2instance
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2424 if netDict
.get('net_id') and is_task_id(netDict
['net_id']):
2425 task_depends
[netDict
['net_id']] = instance_tasks
[netDict
['net_id']]
2426 #skip bridge ifaces not connected to any net
2427 #if 'net_id' not in netDict or netDict['net_id']==None:
2429 myVMDict
['networks'].append(netDict
)
2432 # 'instance_vm_id': instance_vm_uuid,
2433 "instance_net_id": instance_net_id
,
2434 'interface_id': iface
['uuid'],
2435 # 'vim_interface_id': ,
2436 'type': 'external' if iface
['external_name'] is not None else 'internal',
2437 'ip_address': iface
.get('ip_address'),
2438 'floating_ip': int(iface
.get('floating-ip', False)),
2439 'port_security': int(iface
.get('port-security', True))
2441 db_vm_ifaces
.append(db_vm_iface
)
2442 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2443 # print myVMDict['name']
2444 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2445 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2446 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2447 if vm
.get("boot_data"):
2448 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
2450 cloud_config_vm
= cloud_config
2451 if myVMDict
.get('availability_zone'):
2452 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2455 for vm_index
in range(0, vm
.get('count', 1)):
2457 if vm
.get('count', 1) > 1:
2458 vm_index_name
+= "." + chr(97 + vm_index
)
2459 task
= new_task("new-vm", (myVMDict
['name']+vm_index_name
, myVMDict
['description'],
2460 myVMDict
.get('start', None), myVMDict
['imageRef'],
2461 myVMDict
['flavorRef'], myVMDict
['networks'],
2462 cloud_config_vm
, myVMDict
['disks'], av_index
,
2463 vnf_availability_zones
), depends
=task_depends
)
2464 instance_tasks
[task
["id"]] = task
2465 tasks_to_launch
[myvim_thread_id
].append(task
)
2467 vm
['vim_id'] = vm_id
2468 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2469 # put interface uuid back to scenario[vnfs][vms[[interfaces]
2470 for net
in myVMDict
['networks']:
2472 for iface
in vm
['interfaces']:
2473 if net
["name"]==iface
["internal_name"]:
2474 iface
["vim_id"]=net
["vim_id"]
2476 vm_uuid
= str(uuid4())
2477 uuid_list
.append(vm_uuid
)
2480 'instance_vnf_id': vnf_uuid
,
2482 "vm_id": vm
["uuid"],
2485 db_instance_vms
.append(db_vm
)
2486 for db_vm_iface
in db_vm_ifaces
:
2487 iface_uuid
= str(uuid4())
2488 uuid_list
.append(iface_uuid
)
2489 db_vm_iface_instance
= {
2491 "instance_vm_id": vm_uuid
2493 db_vm_iface_instance
.update(db_vm_iface
)
2494 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
2495 ip
= db_vm_iface_instance
.get("ip_address")
2500 ip
= ip
[i
:] + str(int(ip
[:i
]) +1)
2501 db_vm_iface_instance
["ip_address"] = ip
2503 db_vm_iface_instance
["ip_address"] = None
2504 db_instance_interfaces
.append(db_vm_iface_instance
)
2506 scenarioDict
["datacenter2tenant"] = myvim_threads_id
2508 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
2509 db_instance_scenario
['datacenter_id'] = default_datacenter_id
2511 {"instance_scenarios": db_instance_scenario
},
2512 {"instance_vnfs": db_instance_vnfs
},
2513 {"instance_nets": db_instance_nets
},
2514 {"ip_profiles": db_ip_profiles
},
2515 {"instance_vms": db_instance_vms
},
2516 {"instance_interfaces": db_instance_interfaces
},
2519 logger
.debug("create_instance Deployment done scenarioDict: %s",
2520 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2521 mydb
.new_rows(db_tables
, uuid_list
)
2522 for myvim_thread_id
,task_list
in tasks_to_launch
.items():
2523 for task
in task_list
:
2524 vim_threads
["running"][myvim_thread_id
].insert_task(task
)
2526 global_instance_tasks
[instance_uuid
] = instance_tasks
2527 # Update database with those ended instance_tasks
2528 # for task in instance_tasks.values():
2529 # if task["status"] == "ok":
2530 # if task["name"] == "new-vm":
2531 # mydb.update_rows("instance_vms", UPDATE={"vim_vm_id": task["result"]},
2532 # WHERE={"vim_vm_id": task["id"]})
2533 # elif task["name"] == "new-net":
2534 # mydb.update_rows("instance_nets", UPDATE={"vim_net_id": task["result"]},
2535 # WHERE={"vim_net_id": task["id"]})
2536 return mydb
.get_instance_scenario(instance_uuid
)
2537 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2538 message
= rollback(mydb
, myvims
, rollbackList
)
2539 if isinstance(e
, db_base_Exception
):
2540 error_text
= "database Exception"
2541 elif isinstance(e
, vimconn
.vimconnException
):
2542 error_text
= "VIM Exception"
2544 error_text
= "Exception"
2545 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2546 #logger.error("create_instance: %s", error_text)
2547 raise NfvoException(error_text
, e
.http_code
)
2550 def delete_instance(mydb
, tenant_id
, instance_id
):
2551 #print "Checking that the instance_id exists and getting the instance dictionary"
2552 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2553 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2554 tenant_id
= instanceDict
["tenant_id"]
2555 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2557 #1. Delete from Database
2558 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2567 for sce_vnf
in instanceDict
['vnfs']:
2568 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2569 if datacenter_key
not in myvims
:
2571 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2572 except NfvoException
as e
:
2573 logger
.error(str(e
))
2575 myvim_threads
[datacenter_key
] = myvim_thread
2576 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2577 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2579 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2580 sce_vnf
["datacenter_tenant_id"]))
2581 myvims
[datacenter_key
] = None
2583 myvims
[datacenter_key
] = vims
.values()[0]
2584 myvim
= myvims
[datacenter_key
]
2585 myvim_thread
= myvim_threads
[datacenter_key
]
2586 for vm
in sce_vnf
['vms']:
2588 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2592 if is_task_id(vm
['vim_vm_id']):
2593 task_id
= vm
['vim_vm_id']
2594 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2596 error_msg
+= "\n VM was scheduled for create, but task {} is not found".format(task_id
)
2599 if old_task
["status"] == "enqueued":
2600 old_task
["status"] = "deleted"
2601 elif old_task
["status"] == "error":
2603 elif old_task
["status"] == "processing":
2604 task
= new_task("del-vm", (task_id
, vm
["interfaces"]), depends
={task_id
: old_task
})
2606 task
= new_task("del-vm", (old_task
["result"], vm
["interfaces"]))
2608 task
= new_task("del-vm", (vm
['vim_vm_id'], vm
["interfaces"]) )
2610 myvim_thread
.insert_task(task
)
2611 except vimconn
.vimconnNotFoundException
as e
:
2612 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2613 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2614 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2615 except vimconn
.vimconnException
as e
:
2616 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2617 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2618 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2622 for net
in instanceDict
['nets']:
2623 if not net
['created']:
2624 continue #skip not created nets
2625 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2626 if datacenter_key
not in myvims
:
2628 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2629 except NfvoException
as e
:
2630 logger
.error(str(e
))
2632 myvim_threads
[datacenter_key
] = myvim_thread
2633 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2634 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2636 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2637 myvims
[datacenter_key
] = None
2639 myvims
[datacenter_key
] = vims
.values()[0]
2640 myvim
= myvims
[datacenter_key
]
2641 myvim_thread
= myvim_threads
[datacenter_key
]
2644 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2648 if is_task_id(net
['vim_net_id']):
2649 task_id
= net
['vim_net_id']
2650 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2652 error_msg
+= "\n NET was scheduled for create, but task {} is not found".format(task_id
)
2655 if old_task
["status"] == "enqueued":
2656 old_task
["status"] = "deleted"
2657 elif old_task
["status"] == "error":
2659 elif old_task
["status"] == "processing":
2660 task
= new_task("del-net", task_id
, depends
={task_id
: old_task
})
2662 task
= new_task("del-net", old_task
["result"])
2664 task
= new_task("del-net", (net
['vim_net_id'], net
['sdn_net_id']))
2666 myvim_thread
.insert_task(task
)
2667 except vimconn
.vimconnNotFoundException
as e
:
2668 error_msg
+= "\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2669 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2670 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2671 except vimconn
.vimconnException
as e
:
2672 error_msg
+= "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'],
2673 net
["datacenter_id"],
2674 e
.http_code
, str(e
))
2675 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2676 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2677 if len(error_msg
) > 0:
2678 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2680 return 'instance ' + message
+ ' deleted'
2683 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2684 '''Refreshes a scenario instance. It modifies instanceDict'''
2686 - 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
2689 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2690 # #print "nfvo.refresh_instance begins"
2691 # #print json.dumps(instanceDict, indent=4)
2693 # #print "Getting the VIM URL and the VIM tenant_id"
2696 # # 1. Getting VIM vm and net list
2697 # vms_updated = [] #List of VM instance uuids in openmano that were updated
2700 # for sce_vnf in instanceDict['vnfs']:
2701 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
2702 # if datacenter_key not in vm_list:
2703 # vm_list[datacenter_key] = []
2704 # if datacenter_key not in myvims:
2705 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
2706 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
2707 # if len(vims) == 0:
2708 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
2709 # myvims[datacenter_key] = None
2711 # myvims[datacenter_key] = vims.values()[0]
2712 # for vm in sce_vnf['vms']:
2713 # vm_list[datacenter_key].append(vm['vim_vm_id'])
2714 # vms_notupdated.append(vm["uuid"])
2716 # nets_updated = [] #List of VM instance uuids in openmano that were updated
2717 # nets_notupdated=[]
2719 # for net in instanceDict['nets']:
2720 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
2721 # if datacenter_key not in net_list:
2722 # net_list[datacenter_key] = []
2723 # if datacenter_key not in myvims:
2724 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
2725 # datacenter_tenant_id=net["datacenter_tenant_id"])
2726 # if len(vims) == 0:
2727 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
2728 # myvims[datacenter_key] = None
2730 # myvims[datacenter_key] = vims.values()[0]
2732 # net_list[datacenter_key].append(net['vim_net_id'])
2733 # nets_notupdated.append(net["uuid"])
2735 # # 1. Getting the status of all VMs
2737 # for datacenter_key in myvims:
2738 # if not vm_list.get(datacenter_key):
2742 # if not myvims[datacenter_key]:
2743 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2746 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
2748 # except vimconn.vimconnException as e:
2749 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2750 # failed_message = str(e)
2752 # for vm in vm_list[datacenter_key]:
2753 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2755 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2756 # for sce_vnf in instanceDict['vnfs']:
2757 # for vm in sce_vnf['vms']:
2758 # vm_id = vm['vim_vm_id']
2759 # interfaces = vm_dict[vm_id].pop('interfaces', [])
2760 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2761 # has_mgmt_iface = False
2762 # for iface in vm["interfaces"]:
2763 # if iface["type"]=="mgmt":
2764 # has_mgmt_iface = True
2765 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
2766 # vm_dict[vm_id]['status'] = "ACTIVE"
2767 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
2768 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
2769 # 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'):
2770 # vm['status'] = vm_dict[vm_id]['status']
2771 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
2772 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
2773 # # 2.1. Update in openmano DB the VMs whose status changed
2775 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
2776 # vms_notupdated.remove(vm["uuid"])
2778 # vms_updated.append(vm["uuid"])
2779 # except db_base_Exception as e:
2780 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2781 # # 2.2. Update in openmano DB the interface VMs
2782 # for interface in interfaces:
2783 # #translate from vim_net_id to instance_net_id
2784 # network_id_list=[]
2785 # for net in instanceDict['nets']:
2786 # if net["vim_net_id"] == interface["vim_net_id"]:
2787 # network_id_list.append(net["uuid"])
2788 # if not network_id_list:
2790 # del interface["vim_net_id"]
2792 # for network_id in network_id_list:
2793 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
2794 # except db_base_Exception as e:
2795 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
2797 # # 3. Getting the status of all nets
2799 # for datacenter_key in myvims:
2800 # if not net_list.get(datacenter_key):
2803 # failed_message = ""
2804 # if not myvims[datacenter_key]:
2805 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2808 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
2810 # except vimconn.vimconnException as e:
2811 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2812 # failed_message = str(e)
2814 # for net in net_list[datacenter_key]:
2815 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2817 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2818 # # TODO: update nets inside a vnf
2819 # for net in instanceDict['nets']:
2820 # net_id = net['vim_net_id']
2821 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
2822 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
2823 # 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'):
2824 # net['status'] = net_dict[net_id]['status']
2825 # net['error_msg'] = net_dict[net_id].get('error_msg')
2826 # net['vim_info'] = net_dict[net_id].get('vim_info')
2827 # # 5.1. Update in openmano DB the nets whose status changed
2829 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
2830 # nets_notupdated.remove(net["uuid"])
2832 # nets_updated.append(net["uuid"])
2833 # except db_base_Exception as e:
2834 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2836 # # Returns appropriate output
2837 # #print "nfvo.refresh_instance finishes"
2838 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2839 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
2840 instance_id
= instanceDict
['uuid']
2841 # if len(vms_notupdated)+len(nets_notupdated)>0:
2842 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
2843 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
2845 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2848 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2849 #print "Checking that the instance_id exists and getting the instance dictionary"
2850 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2851 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2853 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2854 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2856 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2857 myvim
= vims
.values()[0]
2860 input_vnfs
= action_dict
.pop("vnfs", [])
2861 input_vms
= action_dict
.pop("vms", [])
2862 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2866 for sce_vnf
in instanceDict
['vnfs']:
2867 for vm
in sce_vnf
['vms']:
2868 if not action_over_all
:
2869 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2870 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2873 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2874 if "console" in action_dict
:
2875 if not global_config
["http_console_proxy"]:
2876 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2877 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2878 protocol
=data
["protocol"],
2879 ip
= data
["server"],
2880 port
= data
["port"],
2881 suffix
= data
["suffix"]),
2885 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2886 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2887 "description": "this console is only reachable by local interface",
2892 #print "console data", data
2894 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2895 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2896 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2897 protocol
=data
["protocol"],
2898 ip
= global_config
["http_console_host"],
2899 port
= console_thread
.port
,
2900 suffix
= data
["suffix"]),
2904 except NfvoException
as e
:
2905 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2909 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2911 except vimconn
.vimconnException
as e
:
2912 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2915 if vm_ok
==0: #all goes wrong
2921 def create_or_use_console_proxy_thread(console_server
, console_port
):
2922 #look for a non-used port
2923 console_thread_key
= console_server
+ ":" + str(console_port
)
2924 if console_thread_key
in global_config
["console_thread"]:
2925 #global_config["console_thread"][console_thread_key].start_timeout()
2926 return global_config
["console_thread"][console_thread_key
]
2928 for port
in global_config
["console_port_iterator"]():
2929 #print "create_or_use_console_proxy_thread() port:", port
2930 if port
in global_config
["console_ports"]:
2933 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2935 global_config
["console_thread"][console_thread_key
] = clithread
2936 global_config
["console_ports"][port
] = console_thread_key
2938 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2939 #port used, try with onoher
2941 except cli
.ConsoleProxyException
as e
:
2942 raise NfvoException(str(e
), HTTP_Bad_Request
)
2943 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2946 def check_tenant(mydb
, tenant_id
):
2947 '''check that tenant exists at database'''
2948 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2950 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2954 def new_tenant(mydb
, tenant_dict
):
2955 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2959 def delete_tenant(mydb
, tenant
):
2960 #get nfvo_tenant info
2962 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2963 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2964 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2967 def new_datacenter(mydb
, datacenter_descriptor
):
2968 if "config" in datacenter_descriptor
:
2969 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2970 #Check that datacenter-type is correct
2971 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2974 module
= "vimconn_" + datacenter_type
2975 pkg
= __import__("osm_ro." + module
)
2976 vim_conn
= getattr(pkg
, module
)
2977 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
2978 except (IOError, ImportError):
2979 # if module_info and module_info[0]:
2980 # file.close(module_info[0])
2981 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2983 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2984 return datacenter_id
2987 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2988 # obtain data, check that only one exist
2989 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2992 datacenter_id
= datacenter
['uuid']
2993 where
={'uuid': datacenter
['uuid']}
2994 remove_port_mapping
= False
2995 if "config" in datacenter_descriptor
:
2996 if datacenter_descriptor
['config'] != None:
2998 new_config_dict
= datacenter_descriptor
["config"]
3001 for k
in new_config_dict
:
3002 if new_config_dict
[k
] == None:
3004 if k
== 'sdn-controller':
3005 remove_port_mapping
= True
3007 config_text
= datacenter
.get("config")
3010 config_dict
= yaml
.load(config_text
)
3011 config_dict
.update(new_config_dict
)
3015 except Exception as e
:
3016 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
3018 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
3020 datacenter_descriptor
["config"] = None
3021 if remove_port_mapping
:
3023 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
3024 except ovimException
as e
:
3025 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
3027 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
3028 return datacenter_id
3031 def delete_datacenter(mydb
, datacenter
):
3032 #get nfvo_tenant info
3033 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
3034 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
3036 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
3037 except ovimException
as e
:
3038 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
3039 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
3042 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):
3043 #get datacenter info
3044 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
, vim_passwd
=vim_password
)
3045 datacenter_name
= myvim
["name"]
3047 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
3049 # get nfvo_tenant info
3050 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
3051 if vim_tenant_name
==None:
3052 vim_tenant_name
=tenant_dict
['name']
3054 #check that this association does not exist before
3055 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
3056 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3057 if len(tenants_datacenters
)>0:
3058 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
3060 vim_tenant_id_exist_atdb
=False
3061 if not create_vim_tenant
:
3062 where_
={"datacenter_id": datacenter_id
}
3063 if vim_tenant_id
!=None:
3064 where_
["vim_tenant_id"] = vim_tenant_id
3065 if vim_tenant_name
!=None:
3066 where_
["vim_tenant_name"] = vim_tenant_name
3067 #check if vim_tenant_id is already at database
3068 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
3069 if len(datacenter_tenants_dict
)>=1:
3070 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
3071 vim_tenant_id_exist_atdb
=True
3072 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
3074 datacenter_tenants_dict
= {}
3075 #insert at table datacenter_tenants
3076 else: #if vim_tenant_id==None:
3077 #create tenant at VIM if not provided
3079 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
3080 except vimconn
.vimconnException
as e
:
3081 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
3082 datacenter_tenants_dict
= {}
3083 datacenter_tenants_dict
["created"]="true"
3085 #fill datacenter_tenants table
3086 if not vim_tenant_id_exist_atdb
:
3087 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
3088 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
3089 datacenter_tenants_dict
["user"] = vim_username
3090 datacenter_tenants_dict
["passwd"] = vim_password
3091 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
3093 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
3094 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
3095 datacenter_tenants_dict
["uuid"] = id_
3097 #fill tenants_datacenters table
3098 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
3099 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
3100 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
3102 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
3103 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
3104 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
3105 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
3107 thread_id
= datacenter_tenants_dict
["uuid"]
3108 vim_threads
["running"][thread_id
] = new_thread
3109 return datacenter_id
3112 def edit_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=None, vim_tenant_name
=None,
3113 vim_username
=None, vim_password
=None, config
=None):
3114 #Obtain the data of this datacenter_tenant_id
3115 vim_data
= mydb
.get_rows(
3116 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
3117 "datacenter_tenants.passwd", "datacenter_tenants.config"),
3118 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
3119 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
3120 "tenants_datacenters.datacenter_id": datacenter_id
})
3122 logger
.debug(str(vim_data
))
3123 if len(vim_data
) < 1:
3124 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
3128 v
['config'] = yaml
.load(v
['config'])
3131 v
['vim_tenant_id'] = vim_tenant_id
3133 v
['vim_tenant_name'] = vim_tenant_name
3135 v
['user'] = vim_username
3137 v
['passwd'] = vim_password
3141 v
['config'].update(config
)
3143 logger
.debug(str(v
))
3144 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
3145 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
3146 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
3148 return datacenter_id
3150 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
3151 #get datacenter info
3152 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
3154 #get nfvo_tenant info
3155 if not tenant_id
or tenant_id
=="any":
3158 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
3159 tenant_uuid
= tenant_dict
['uuid']
3161 #check that this association exist before
3162 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
3164 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
3165 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3166 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
3167 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
3169 #delete this association
3170 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3172 #get vim_tenant info and deletes
3174 for tenant_datacenter_item
in tenant_datacenter_list
:
3175 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
3176 #try to delete vim:tenant
3178 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
3179 if vim_tenant_dict
['created']=='true':
3180 #delete tenant at VIM if created by NFVO
3182 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
3183 except vimconn
.vimconnException
as e
:
3184 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
3185 logger
.warn(warning
)
3186 except db_base_Exception
as e
:
3187 logger
.error("Cannot delete datacenter_tenants " + str(e
))
3188 pass # the error will be caused because dependencies, vim_tenant can not be deleted
3189 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
3190 thread
= vim_threads
["running"][thread_id
]
3191 thread
.insert_task(new_task("exit", None))
3192 vim_threads
["deleting"][thread_id
] = thread
3193 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
3196 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
3198 #get datacenter info
3199 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3201 if 'net-update' in action_dict
:
3203 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
3205 except vimconn
.vimconnException
as e
:
3206 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
3207 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3208 #update nets Change from VIM format to NFVO format
3211 net_nfvo
={'datacenter_id': datacenter_id
}
3212 net_nfvo
['name'] = net
['name']
3213 #net_nfvo['description']= net['name']
3214 net_nfvo
['vim_net_id'] = net
['id']
3215 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3216 net_nfvo
['shared'] = net
['shared']
3217 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3218 net_list
.append(net_nfvo
)
3219 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
3220 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
3222 elif 'net-edit' in action_dict
:
3223 net
= action_dict
['net-edit'].pop('net')
3224 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3225 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
3226 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3228 elif 'net-delete' in action_dict
:
3229 net
= action_dict
['net-deelte'].get('net')
3230 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3231 result
= mydb
.delete_row(FROM
='datacenter_nets',
3232 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3236 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
3239 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
3240 #get datacenter info
3241 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3243 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
3244 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
3245 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
3249 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
3250 #get datacenter info
3251 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3254 action_dict
= action_dict
["netmap"]
3255 if 'vim_id' in action_dict
:
3256 filter_dict
["id"] = action_dict
['vim_id']
3257 if 'vim_name' in action_dict
:
3258 filter_dict
["name"] = action_dict
['vim_name']
3260 filter_dict
["shared"] = True
3263 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
3264 except vimconn
.vimconnException
as e
:
3265 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
3266 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3267 if len(vim_nets
)>1 and action_dict
:
3268 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
3269 elif len(vim_nets
)==0: # and action_dict:
3270 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
3272 for net
in vim_nets
:
3273 net_nfvo
={'datacenter_id': datacenter_id
}
3274 if action_dict
and "name" in action_dict
:
3275 net_nfvo
['name'] = action_dict
['name']
3277 net_nfvo
['name'] = net
['name']
3278 #net_nfvo['description']= net['name']
3279 net_nfvo
['vim_net_id'] = net
['id']
3280 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3281 net_nfvo
['shared'] = net
['shared']
3282 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3284 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
3285 net_nfvo
["status"] = "OK"
3286 net_nfvo
["uuid"] = net_id
3287 except db_base_Exception
as e
:
3291 net_nfvo
["status"] = "FAIL: " + str(e
)
3292 net_list
.append(net_nfvo
)
3295 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
3296 # obtain all network data
3298 if utils
.check_valid_uuid(network_id
):
3299 filter_dict
= {"id": network_id
}
3301 filter_dict
= {"name": network_id
}
3303 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3304 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
3305 except vimconn
.vimconnException
as e
:
3306 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
3307 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
3309 # ensure the network is defined
3310 if len(network
) == 0:
3311 raise NfvoException("Network {} is not present in the system".format(network_id
),
3314 # ensure there is only one network with the provided name
3315 if len(network
) > 1:
3316 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), HTTP_Bad_Request
)
3318 # ensure it is a dataplane network
3319 if network
[0]['type'] != 'data':
3322 # ensure we use the id
3323 network_id
= network
[0]['id']
3325 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
3326 # and with instance_scenario_id==NULL
3327 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
3328 search_dict
= {'vim_net_id': network_id
}
3331 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
3332 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
3333 except db_base_Exception
as e
:
3334 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
3335 network_id
) + str(e
), HTTP_Internal_Server_Error
)
3339 if net
['sdn_net_id'] != None:
3341 sdn_net_id
= net
['sdn_net_id']
3343 if sdn_net_counter
== 0:
3345 elif sdn_net_counter
== 1:
3348 raise NfvoException("More than one SDN network is associated to vim network {}".format(
3349 network_id
), HTTP_Internal_Server_Error
)
3351 def get_sdn_controller_id(mydb
, datacenter
):
3352 # Obtain sdn controller id
3353 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
3357 return yaml
.load(config
).get('sdn-controller')
3359 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
3361 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
3362 if not sdn_network_id
:
3363 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), HTTP_Internal_Server_Error
)
3365 #Obtain sdn controller id
3366 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
3367 if not controller_id
:
3368 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), HTTP_Internal_Server_Error
)
3370 #Obtain sdn controller info
3371 sdn_controller
= ovim
.show_of_controller(controller_id
)
3374 'name': 'external_port',
3375 'net_id': sdn_network_id
,
3376 'ofc_id': controller_id
,
3377 'switch_dpid': sdn_controller
['dpid'],
3378 'switch_port': descriptor
['port']
3381 if 'vlan' in descriptor
:
3382 port_data
['vlan'] = descriptor
['vlan']
3383 if 'mac' in descriptor
:
3384 port_data
['mac'] = descriptor
['mac']
3386 result
= ovim
.new_port(port_data
)
3387 except ovimException
as e
:
3388 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
3389 sdn_network_id
, network_id
) + str(e
), HTTP_Internal_Server_Error
)
3390 except db_base_Exception
as e
:
3391 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
3392 network_id
) + str(e
), HTTP_Internal_Server_Error
)
3394 return 'Port uuid: '+ result
3396 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
3398 filter = {'uuid': port_id
}
3400 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
3401 if not sdn_network_id
:
3402 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
3403 HTTP_Internal_Server_Error
)
3404 #in case no port_id is specified only ports marked as 'external_port' will be detached
3405 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
3408 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
3409 except ovimException
as e
:
3410 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
3411 HTTP_Internal_Server_Error
)
3413 if len(port_list
) == 0:
3414 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
3418 for port
in port_list
:
3420 port_uuid_list
.append(port
['uuid'])
3421 ovim
.delete_port(port
['uuid'])
3422 except ovimException
as e
:
3423 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), HTTP_Internal_Server_Error
)
3425 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
3427 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
3428 #get datacenter info
3429 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3432 if utils
.check_valid_uuid(name
):
3433 filter_dict
["id"] = name
3435 filter_dict
["name"] = name
3437 if item
=="networks":
3438 #filter_dict['tenant_id'] = myvim['tenant_id']
3439 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
3441 if len(content
) == 0:
3442 raise NfvoException("Network {} is not present in the system. ".format(name
),
3445 #Update the networks with the attached ports
3447 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
3448 if sdn_network_id
!= None:
3450 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
3451 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
3452 except ovimException
as e
:
3453 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), HTTP_Internal_Server_Error
)
3454 #Remove field name and if port name is external_port save it as 'type'
3455 for port
in port_list
:
3456 if port
['name'] == 'external_port':
3457 port
['type'] = "External"
3459 net
['sdn_network_id'] = sdn_network_id
3460 net
['sdn_attached_ports'] = port_list
3462 elif item
=="tenants":
3463 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
3464 elif item
== "images":
3466 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
3468 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3469 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
3470 if name
and len(content
)==1:
3471 return {item
[:-1]: content
[0]}
3472 elif name
and len(content
)==0:
3473 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
3476 return {item
: content
}
3477 except vimconn
.vimconnException
as e
:
3478 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
3479 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
3482 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
3483 #get datacenter info
3484 if tenant_id
== "any":
3487 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3489 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
3490 logger
.debug("vim_action_delete vim response: " + str(content
))
3491 items
= content
.values()[0]
3492 if type(items
)==list and len(items
)==0:
3493 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
3494 elif type(items
)==list and len(items
)>1:
3495 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
3496 else: # it is a dict
3497 item_id
= items
["id"]
3498 item_name
= str(items
.get("name"))
3501 if item
=="networks":
3502 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
3503 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
3504 if sdn_network_id
!= None:
3505 #Delete any port attachment to this network
3507 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
3508 except ovimException
as e
:
3509 raise NfvoException(
3510 "ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
3511 HTTP_Internal_Server_Error
)
3513 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
3514 for port
in port_list
:
3515 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
3517 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
3519 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id
, 'vim_net_id': item_id
})
3520 except db_base_Exception
as e
:
3521 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
3522 str(e
), HTTP_Internal_Server_Error
)
3524 #Delete the SDN network
3526 ovim
.delete_network(sdn_network_id
)
3527 except ovimException
as e
:
3528 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
3529 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
3530 HTTP_Internal_Server_Error
)
3532 content
= myvim
.delete_network(item_id
)
3533 elif item
=="tenants":
3534 content
= myvim
.delete_tenant(item_id
)
3535 elif item
== "images":
3536 content
= myvim
.delete_image(item_id
)
3538 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3539 except vimconn
.vimconnException
as e
:
3540 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
3541 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
3543 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
3546 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
3547 #get datacenter info
3548 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
3549 if tenant_id
== "any":
3551 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3553 if item
=="networks":
3554 net
= descriptor
["network"]
3555 net_name
= net
.pop("name")
3556 net_type
= net
.pop("type", "bridge")
3557 net_public
= net
.pop("shared", False)
3558 net_ipprofile
= net
.pop("ip_profile", None)
3559 net_vlan
= net
.pop("vlan", None)
3560 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
3562 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
3563 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
3566 sdn_network
['vlan'] = net_vlan
3567 sdn_network
['type'] = net_type
3568 sdn_network
['name'] = net_name
3569 ovim_content
= ovim
.new_network(sdn_network
)
3570 except ovimException
as e
:
3571 self
.logger
.error("ovimException creating SDN network={} ".format(
3572 sdn_network
) + str(e
), exc_info
=True)
3573 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
3574 HTTP_Internal_Server_Error
)
3576 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
3577 # use instance_scenario_id=None to distinguish from real instaces of nets
3578 correspondence
= {'instance_scenario_id': None, 'sdn_net_id': ovim_content
, 'vim_net_id': content
}
3579 #obtain datacenter_tenant_id
3580 correspondence
['datacenter_tenant_id'] = mydb
.get_rows(SELECT
=('uuid',), FROM
='datacenter_tenants', WHERE
={'datacenter_id': datacenter
})[0]['uuid']
3583 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
3584 except db_base_Exception
as e
:
3585 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
3586 str(e
), HTTP_Internal_Server_Error
)
3587 elif item
=="tenants":
3588 tenant
= descriptor
["tenant"]
3589 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
3591 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3592 except vimconn
.vimconnException
as e
:
3593 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
3595 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
3597 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
3598 data
= ovim
.new_of_controller(sdn_controller
)
3599 logger
.debug('New SDN controller created with uuid {}'.format(data
))
3602 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
3603 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
3604 msg
= 'SDN controller {} updated'.format(data
)
3608 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
3609 if controller_id
== None:
3610 data
= ovim
.get_of_controllers()
3612 data
= ovim
.show_of_controller(controller_id
)
3614 msg
= 'SDN controller list:\n {}'.format(data
)
3618 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
3619 select_
= ('uuid', 'config')
3620 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
3621 for datacenter
in datacenters
:
3622 if datacenter
['config']:
3623 config
= yaml
.load(datacenter
['config'])
3624 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
3625 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
3627 data
= ovim
.delete_of_controller(controller_id
)
3628 msg
= 'SDN controller {} deleted'.format(data
)
3632 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
3633 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
3634 if len(controller
) < 1:
3635 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
3638 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
3640 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
3642 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
3643 switch_dpid
= sdn_controller
["dpid"]
3646 for compute_node
in sdn_port_mapping
:
3647 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
3649 element
["compute_node"] = compute_node
["compute_node"]
3650 for port
in compute_node
["ports"]:
3651 element
["pci"] = port
.get("pci")
3652 element
["switch_port"] = port
.get("switch_port")
3653 element
["switch_mac"] = port
.get("switch_mac")
3654 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
3655 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
3656 " or 'switch_mac'", HTTP_Bad_Request
)
3657 maps
.append(dict(element
))
3659 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
3661 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
3662 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
3665 "sdn-controller": None,
3666 "datacenter-id": datacenter_id
,
3668 "ports_mapping": list()
3671 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
3672 if datacenter
['config']:
3673 config
= yaml
.load(datacenter
['config'])
3674 if 'sdn-controller' in config
:
3675 controller_id
= config
['sdn-controller']
3676 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
3677 result
["sdn-controller"] = controller_id
3678 result
["dpid"] = sdn_controller
["dpid"]
3680 if result
["sdn-controller"] == None:
3681 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), HTTP_Bad_Request
)
3682 if result
["dpid"] == None:
3683 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
3684 HTTP_Internal_Server_Error
)
3689 ports_correspondence_dict
= dict()
3691 if result
["sdn-controller"] != link
["ofc_id"]:
3692 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
3693 if result
["dpid"] != link
["switch_dpid"]:
3694 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
3696 element
["pci"] = link
["pci"]
3697 if link
["switch_port"]:
3698 element
["switch_port"] = link
["switch_port"]
3699 if link
["switch_mac"]:
3700 element
["switch_mac"] = link
["switch_mac"]
3702 if not link
["compute_node"] in ports_correspondence_dict
:
3704 content
["compute_node"] = link
["compute_node"]
3705 content
["ports"] = list()
3706 ports_correspondence_dict
[link
["compute_node"]] = content
3708 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
3710 for key
in sorted(ports_correspondence_dict
):
3711 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
3715 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
3716 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})