1 # -*- coding: utf-8 -*-
4 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
5 # This file is part of openmano
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
25 NFVO engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances
27 __author__
="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
28 __date__
="$16-sep-2014 22:05:01$"
35 from db_base
import HTTP_Unauthorized
, HTTP_Bad_Request
, HTTP_Internal_Server_Error
, HTTP_Not_Found
,\
36 HTTP_Conflict
, HTTP_Method_Not_Allowed
37 import console_proxy_thread
as cli
41 from db_base
import db_base_Exception
44 from threading
import Lock
46 from lib_osm_openvim
import ovim
as ovim_module
49 global vimconn_imported
51 global default_volume_size
52 default_volume_size
= '5' #size in GB
57 vimconn_imported
= {} # dictionary with VIM type as key, loaded module as value
58 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
59 vim_persistent_info
= {}
60 logger
= logging
.getLogger('openmano.nfvo')
62 global_instance_tasks
= {}
67 class NfvoException(Exception):
68 def __init__(self
, message
, http_code
):
69 self
.http_code
= http_code
70 Exception.__init
__(self
, message
)
76 if task_id
<= last_task_id
:
77 task_id
= last_task_id
+ 0.000001
78 last_task_id
= task_id
79 return "TASK.{:.6f}".format(task_id
)
82 def new_task(name
, params
, depends
=None):
83 task_id
= get_task_id()
84 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
86 task
["depends"] = depends
91 return True if id[:5] == "TASK." else False
94 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
95 name
= datacenter_name
[:16]
96 if name
not in vim_threads
["names"]:
97 vim_threads
["names"].append(name
)
99 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
100 if name
not in vim_threads
["names"]:
101 vim_threads
["names"].append(name
)
103 name
= datacenter_id
+ "-" + tenant_id
104 vim_threads
["names"].append(name
)
108 def start_service(mydb
):
109 global db
, global_config
110 db
= nfvo_db
.nfvo_db()
111 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
114 # Initialize openvim for SDN control
115 # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
116 # TODO: review ovim.py to delete not needed configuration
117 ovim_configuration
= {
118 'logger_name': 'openmano.ovim',
119 'network_vlan_range_start': 1000,
120 'network_vlan_range_end': 4096,
121 'db_name': global_config
["db_ovim_name"],
122 'db_host': global_config
["db_ovim_host"],
123 'db_user': global_config
["db_ovim_user"],
124 'db_passwd': global_config
["db_ovim_passwd"],
127 'network_type': 'bridge',
128 #TODO: log_level_of should not be needed. To be modified in ovim
129 'log_level_of': 'DEBUG'
132 ovim
= ovim_module
.ovim(ovim_configuration
)
135 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\
136 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
137 select_
= ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin',
138 'd.name as datacenter_name', 'dt.uuid as datacenter_tenant_id',
139 'dt.vim_tenant_name as vim_tenant_name', 'dt.vim_tenant_id as vim_tenant_id',
140 'user', 'passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
141 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
143 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
144 'datacenter_id': vim
.get('datacenter_id')}
146 extra
.update(yaml
.load(vim
["config"]))
147 if vim
.get('dt_config'):
148 extra
.update(yaml
.load(vim
["dt_config"]))
149 if vim
["type"] not in vimconn_imported
:
152 module
= "vimconn_" + vim
["type"]
153 pkg
= __import__("osm_ro." + module
)
154 vim_conn
= getattr(pkg
, module
)
155 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
156 # vim_conn = imp.load_module(vim["type"], *module_info)
157 vimconn_imported
[vim
["type"]] = vim_conn
158 except (IOError, ImportError) as e
:
159 # if module_info and module_info[0]:
160 # file.close(module_info[0])
161 raise NfvoException("Unknown vim type '{}'. Cannot open file '{}.py'; {}: {}".format(
162 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
164 thread_id
= vim
['datacenter_tenant_id']
165 vim_persistent_info
[thread_id
] = {}
168 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
169 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
170 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
171 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
172 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
173 user
=vim
['user'], passwd
=vim
['passwd'],
174 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
176 except Exception as e
:
177 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, e
),
178 HTTP_Internal_Server_Error
)
179 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['vim_tenant_id'], vim
['vim_tenant_name'],
180 vim
['vim_tenant_id'])
181 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, vim
['datacenter_name'],
182 vim
['datacenter_tenant_id'], db
=db
, db_lock
=db_lock
, ovim
=ovim
)
184 vim_threads
["running"][thread_id
] = new_thread
185 except db_base_Exception
as e
:
186 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
187 except ovim_module
.ovimException
as e
:
189 if message
[:22] == "DATABASE wrong version":
190 message
= "DATABASE wrong version of lib_osm_openvim {msg} -d{dbname} -u{dbuser} -p{dbpass} {ver}' "\
191 "at host {dbhost}".format(
192 msg
=message
[22:-3], dbname
=global_config
["db_ovim_name"],
193 dbuser
=global_config
["db_ovim_user"], dbpass
=global_config
["db_ovim_passwd"],
194 ver
=message
[-3:-1], dbhost
=global_config
["db_ovim_host"])
195 raise NfvoException(message
, HTTP_Bad_Request
)
199 global ovim
, global_config
202 for thread_id
,thread
in vim_threads
["running"].items():
203 thread
.insert_task(new_task("exit", None))
204 vim_threads
["deleting"][thread_id
] = thread
205 vim_threads
["running"] = {}
206 if global_config
and global_config
.get("console_thread"):
207 for thread
in global_config
["console_thread"]:
208 thread
.terminate
= True
211 return ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config
["version"],
212 global_config
["version_date"] ))
215 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
217 return result, content:
218 <0, error_text upon error
219 nb_records, flavor_list on success
222 WHERE_dict
['vnf_id'] = vnf_id
223 if nfvo_tenant
is not None:
224 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
226 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
227 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
228 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
229 #print "get_flavor_list result:", result
230 #print "get_flavor_list content:", content
232 for flavor
in flavors
:
233 flavorList
.append(flavor
['flavor_id'])
237 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
239 return result, content:
240 <0, error_text upon error
241 nb_records, flavor_list on success
244 WHERE_dict
['vnf_id'] = vnf_id
245 if nfvo_tenant
is not None:
246 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
248 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
249 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
252 imageList
.append(image
['image_id'])
256 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
257 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
258 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
259 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
260 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
261 raise exception upon error
264 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
265 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
266 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
267 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
268 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
269 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
270 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
271 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'
272 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
273 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
274 'user','passwd', 'dt.config as dt_config')
276 from_
= 'datacenters as d'
277 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
279 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
282 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
283 'datacenter_id': vim
.get('datacenter_id')}
285 extra
.update(yaml
.load(vim
["config"]))
286 if vim
.get('dt_config'):
287 extra
.update(yaml
.load(vim
["dt_config"]))
288 if vim
["type"] not in vimconn_imported
:
291 module
= "vimconn_" + vim
["type"]
292 pkg
= __import__("osm_ro." + module
)
293 vim_conn
= getattr(pkg
, module
)
294 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
295 # vim_conn = imp.load_module(vim["type"], *module_info)
296 vimconn_imported
[vim
["type"]] = vim_conn
297 except (IOError, ImportError) as e
:
298 # if module_info and module_info[0]:
299 # file.close(module_info[0])
300 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
301 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
304 if 'datacenter_tenant_id' in vim
:
305 thread_id
= vim
["datacenter_tenant_id"]
306 if thread_id
not in vim_persistent_info
:
307 vim_persistent_info
[thread_id
] = {}
308 persistent_info
= vim_persistent_info
[thread_id
]
312 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
313 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
314 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
315 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
316 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
317 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
318 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
319 config
=extra
, persistent_info
=persistent_info
321 except Exception as e
:
322 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
324 except db_base_Exception
as e
:
325 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
328 def rollback(mydb
, vims
, rollback_list
):
330 #delete things by reverse order
331 for i
in range(len(rollback_list
)-1, -1, -1):
332 item
= rollback_list
[i
]
333 if item
["where"]=="vim":
334 if item
["vim_id"] not in vims
:
336 vim
=vims
[ item
["vim_id"] ]
338 if item
["what"]=="image":
339 vim
.delete_image(item
["uuid"])
340 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
341 elif item
["what"]=="flavor":
342 vim
.delete_flavor(item
["uuid"])
343 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
344 elif item
["what"]=="network":
345 vim
.delete_network(item
["uuid"])
346 elif item
["what"]=="vm":
347 vim
.delete_vminstance(item
["uuid"])
348 except vimconn
.vimconnException
as e
:
349 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
350 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
351 except db_base_Exception
as e
:
352 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
356 if item
["what"]=="image":
357 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
358 elif item
["what"]=="flavor":
359 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
360 except db_base_Exception
as e
:
361 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
362 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
363 if len(undeleted_items
)==0:
364 return True," Rollback successful."
366 return False," Rollback fails to delete: " + str(undeleted_items
)
369 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
371 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
373 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
375 #dataplane interfaces
376 for numa
in vnfc
.get("numas",() ):
377 for interface
in numa
.get("interfaces",()):
378 if interface
["name"] in name_dict
:
380 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
381 vnfc
["name"], interface
["name"]),
383 name_dict
[ interface
["name"] ] = "underlay"
385 for interface
in vnfc
.get("bridge-ifaces",() ):
386 if interface
["name"] in name_dict
:
388 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
389 vnfc
["name"], interface
["name"]),
391 name_dict
[ interface
["name"] ] = "overlay"
392 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
393 # check bood-data info
394 if "boot-data" in vnfc
:
395 # check that user-data is incompatible with users and config-files
396 if (vnfc
["boot-data"].get("users") or vnfc
["boot-data"].get("config-files")) and vnfc
["boot-data"].get("user-data"):
398 "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
401 #check if the info in external_connections matches with the one in the vnfcs
403 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
404 if external_connection
["name"] in name_list
:
406 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
407 external_connection
["name"]),
409 name_list
.append(external_connection
["name"])
410 if external_connection
["VNFC"] not in vnfc_interfaces
:
412 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
413 external_connection
["name"], external_connection
["VNFC"]),
416 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
418 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
419 external_connection
["name"],
420 external_connection
["local_iface_name"]),
423 #check if the info in internal_connections matches with the one in the vnfcs
425 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
426 if internal_connection
["name"] in name_list
:
428 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
429 internal_connection
["name"]),
431 name_list
.append(internal_connection
["name"])
432 #We should check that internal-connections of type "ptp" have only 2 elements
434 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
436 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
437 internal_connection
["name"],
438 'ptp' if vnf_descriptor_version
==1 else 'e-line',
439 'data' if vnf_descriptor_version
==1 else "e-lan"),
441 for port
in internal_connection
["elements"]:
443 iface
= port
["local_iface_name"]
444 if vnf
not in vnfc_interfaces
:
446 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
447 internal_connection
["name"], vnf
),
449 if iface
not in vnfc_interfaces
[ vnf
]:
451 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
452 internal_connection
["name"], iface
),
454 return -HTTP_Bad_Request
,
455 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
456 if vnfc_interfaces
[vnf
][iface
] == "overlay":
457 internal_connection
["type"] = "bridge"
459 internal_connection
["type"] = "data"
460 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
461 if vnfc_interfaces
[vnf
][iface
] == "overlay":
462 internal_connection
["implementation"] = "overlay"
464 internal_connection
["implementation"] = "underlay"
465 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
466 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
468 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
469 internal_connection
["name"],
470 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
471 'data' if vnf_descriptor_version
==1 else 'underlay'),
473 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
474 vnfc_interfaces
[vnf
][iface
] == "underlay":
476 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
477 internal_connection
["name"], iface
,
478 'data' if vnf_descriptor_version
==1 else 'underlay',
479 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
483 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
485 if only_create_at_vim
:
486 image_mano_id
= image_dict
['uuid']
487 if return_on_error
== None:
488 return_on_error
= True
490 if image_dict
['location']:
491 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
493 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
495 image_mano_id
= images
[0]['uuid']
497 #create image in MANO DB
498 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
499 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
500 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
502 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
503 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
504 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
505 #create image at every vim
506 for vim_id
,vim
in vims
.iteritems():
507 image_created
="false"
509 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
510 #look at VIM if this image exist
512 if image_dict
['location'] is not None:
513 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
516 filter_dict
['name'] = image_dict
['universal_name']
517 if image_dict
.get('checksum') != None:
518 filter_dict
['checksum'] = image_dict
['checksum']
519 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
520 vim_images
= vim
.get_image_list(filter_dict
)
521 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
522 if len(vim_images
) > 1:
523 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), HTTP_Conflict
)
524 elif len(vim_images
) == 0:
525 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
527 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
528 image_vim_id
= vim_images
[0]['id']
530 except vimconn
.vimconnNotFoundException
as e
:
531 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
533 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
534 if image_dict
['location']:
535 image_vim_id
= vim
.new_image(image_dict
)
536 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
539 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
540 raise vimconn
.vimconnException(str(e
))
541 except vimconn
.vimconnException
as e
:
543 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
546 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
548 except vimconn
.vimconnException
as e
:
550 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
552 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
555 #if we reach here, the image has been created or existed
557 #add new vim_id at datacenters_images
558 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
559 elif image_db
[0]["vim_id"]!=image_vim_id
:
560 #modify existing vim_id at datacenters_images
561 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
563 return image_vim_id
if only_create_at_vim
else image_mano_id
566 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
567 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
568 'ram':flavor_dict
.get('ram'),
569 'vcpus':flavor_dict
.get('vcpus'),
571 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
572 del flavor_dict
['extended']
573 if 'extended' in flavor_dict
:
574 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
576 #look if flavor exist
577 if only_create_at_vim
:
578 flavor_mano_id
= flavor_dict
['uuid']
579 if return_on_error
== None:
580 return_on_error
= True
582 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
584 flavor_mano_id
= flavors
[0]['uuid']
587 #create one by one the images of aditional disks
588 dev_image_list
=[] #list of images
589 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
591 for device
in flavor_dict
['extended'].get('devices',[]):
592 if "image" not in device
and "image name" not in device
:
595 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
596 image_dict
['universal_name']=device
.get('image name')
597 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
598 image_dict
['location']=device
.get('image')
599 #image_dict['new_location']=vnfc.get('image location')
600 image_dict
['checksum']=device
.get('image checksum')
601 image_metadata_dict
= device
.get('image metadata', None)
602 image_metadata_str
= None
603 if image_metadata_dict
!= None:
604 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
605 image_dict
['metadata']=image_metadata_str
606 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
607 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
608 dev_image_list
.append(image_id
)
610 temp_flavor_dict
['name'] = flavor_dict
['name']
611 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
612 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
613 flavor_mano_id
= content
614 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
615 #create flavor at every vim
616 if 'uuid' in flavor_dict
:
617 del flavor_dict
['uuid']
619 for vim_id
,vim
in vims
.items():
620 flavor_created
="false"
622 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
623 #look at VIM if this flavor exist SKIPPED
624 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
626 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
630 #Create the flavor in VIM
631 #Translate images at devices from MANO id to VIM id
633 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
634 #make a copy of original devices
637 for device
in flavor_dict
["extended"].get("devices",[]):
640 devices_original
.append(dev
)
641 if 'image' in device
:
643 if 'image metadata' in device
:
644 del device
['image metadata']
646 for index
in range(0,len(devices_original
)) :
647 device
=devices_original
[index
]
648 if "image" not in device
and "image name" not in device
:
650 disk_list
.append({'size': device
.get('size', default_volume_size
)})
653 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
654 image_dict
['universal_name']=device
.get('image name')
655 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
656 image_dict
['location']=device
.get('image')
657 #image_dict['new_location']=device.get('image location')
658 image_dict
['checksum']=device
.get('image checksum')
659 image_metadata_dict
= device
.get('image metadata', None)
660 image_metadata_str
= None
661 if image_metadata_dict
!= None:
662 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
663 image_dict
['metadata']=image_metadata_str
664 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
665 image_dict
["uuid"]=image_mano_id
666 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
668 #save disk information (image must be based on and size
669 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
671 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
674 #check that this vim_id exist in VIM, if not create
675 flavor_vim_id
=flavor_db
[0]["vim_id"]
677 vim
.get_flavor(flavor_vim_id
)
678 continue #flavor exist
679 except vimconn
.vimconnException
:
681 #create flavor at vim
682 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
685 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
686 flavor_create
="false"
687 except vimconn
.vimconnException
as e
:
690 if not flavor_vim_id
:
691 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
692 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
693 flavor_created
="true"
694 except vimconn
.vimconnException
as e
:
696 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
698 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
701 #if reach here the flavor has been create or exist
702 if len(flavor_db
)==0:
703 #add new vim_id at datacenters_flavors
704 extended_devices_yaml
= None
705 if len(disk_list
) > 0:
706 extended_devices
= dict()
707 extended_devices
['disks'] = disk_list
708 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
709 mydb
.new_row('datacenters_flavors',
710 {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
,
711 'created':flavor_created
,'extended': extended_devices_yaml
})
712 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
713 #modify existing vim_id at datacenters_flavors
714 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
716 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
719 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
722 # Step 1. Check the VNF descriptor
723 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
724 # Step 2. Check tenant exist
726 if tenant_id
!= "any":
727 check_tenant(mydb
, tenant_id
)
728 if "tenant_id" in vnf_descriptor
["vnf"]:
729 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
730 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
733 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
734 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
735 if global_config
["auto_push_VNF_to_VIMs"]:
736 vims
= get_vim(mydb
, tenant_id
)
738 # Step 4. Review the descriptor and add missing fields
739 #print vnf_descriptor
740 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
741 vnf_name
= vnf_descriptor
['vnf']['name']
742 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
743 if "physical" in vnf_descriptor
['vnf']:
744 del vnf_descriptor
['vnf']['physical']
745 #print vnf_descriptor
747 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
748 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
749 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
751 #For each VNFC, we add it to the VNFCDict and we create a flavor.
752 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
753 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
755 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
756 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
758 VNFCitem
["name"] = vnfc
['name']
759 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
761 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
764 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
765 myflavorDict
["description"] = VNFCitem
["description"]
766 myflavorDict
["ram"] = vnfc
.get("ram", 0)
767 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
768 myflavorDict
["disk"] = vnfc
.get("disk", 1)
769 myflavorDict
["extended"] = {}
771 devices
= vnfc
.get("devices")
773 myflavorDict
["extended"]["devices"] = devices
776 # 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
777 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
779 # Previous code has been commented
780 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
781 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
782 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
783 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
785 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
787 # print "Error creating flavor: unknown processor model. Rollback successful."
788 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
790 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
791 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
793 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
794 myflavorDict
['extended']['numas'] = vnfc
['numas']
798 # Step 6.2 New flavors are created in the VIM
799 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
801 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
802 VNFCitem
["flavor_id"] = flavor_id
803 VNFCDict
[vnfc
['name']] = VNFCitem
805 logger
.debug("Creating new images in the VIM for each VNFC")
806 # Step 6.3 New images are created in the VIM
807 #For each VNFC, we must create the appropriate image.
808 #This "for" loop might be integrated with the previous one
809 #In case this integration is made, the VNFCDict might become a VNFClist.
810 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
811 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
813 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
814 image_dict
['universal_name']=vnfc
.get('image name')
815 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
816 image_dict
['location']=vnfc
.get('VNFC image')
817 #image_dict['new_location']=vnfc.get('image location')
818 image_dict
['checksum']=vnfc
.get('image checksum')
819 image_metadata_dict
= vnfc
.get('image metadata', None)
820 image_metadata_str
= None
821 if image_metadata_dict
is not None:
822 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
823 image_dict
['metadata']=image_metadata_str
824 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
825 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
826 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
827 VNFCDict
[vnfc
['name']]["image_id"] = image_id
828 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
829 if vnfc
.get("boot-data"):
830 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
833 # Step 7. Storing the VNF descriptor in the repository
834 if "descriptor" not in vnf_descriptor
["vnf"]:
835 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
837 # Step 8. Adding the VNF to the NFVO DB
838 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
840 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
841 _
, message
= rollback(mydb
, vims
, rollback_list
)
842 if isinstance(e
, db_base_Exception
):
843 error_text
= "Exception at database"
844 elif isinstance(e
, KeyError):
845 error_text
= "KeyError exception "
846 e
.http_code
= HTTP_Internal_Server_Error
848 error_text
= "Exception at VIM"
849 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
850 #logger.error("start_scenario %s", error_text)
851 raise NfvoException(error_text
, e
.http_code
)
854 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
857 # Step 1. Check the VNF descriptor
858 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
859 # Step 2. Check tenant exist
861 if tenant_id
!= "any":
862 check_tenant(mydb
, tenant_id
)
863 if "tenant_id" in vnf_descriptor
["vnf"]:
864 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
865 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
868 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
869 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
870 if global_config
["auto_push_VNF_to_VIMs"]:
871 vims
= get_vim(mydb
, tenant_id
)
873 # Step 4. Review the descriptor and add missing fields
874 #print vnf_descriptor
875 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
876 vnf_name
= vnf_descriptor
['vnf']['name']
877 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
878 if "physical" in vnf_descriptor
['vnf']:
879 del vnf_descriptor
['vnf']['physical']
880 #print vnf_descriptor
882 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
883 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
884 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
886 #For each VNFC, we add it to the VNFCDict and we create a flavor.
887 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
888 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
890 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
891 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
893 VNFCitem
["name"] = vnfc
['name']
894 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
896 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
899 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
900 myflavorDict
["description"] = VNFCitem
["description"]
901 myflavorDict
["ram"] = vnfc
.get("ram", 0)
902 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
903 myflavorDict
["disk"] = vnfc
.get("disk", 1)
904 myflavorDict
["extended"] = {}
906 devices
= vnfc
.get("devices")
908 myflavorDict
["extended"]["devices"] = devices
911 # 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
912 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
914 # Previous code has been commented
915 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
916 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
917 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
918 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
920 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
922 # print "Error creating flavor: unknown processor model. Rollback successful."
923 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
925 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
926 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
928 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
929 myflavorDict
['extended']['numas'] = vnfc
['numas']
933 # Step 6.2 New flavors are created in the VIM
934 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
936 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
937 VNFCitem
["flavor_id"] = flavor_id
938 VNFCDict
[vnfc
['name']] = VNFCitem
940 logger
.debug("Creating new images in the VIM for each VNFC")
941 # Step 6.3 New images are created in the VIM
942 #For each VNFC, we must create the appropriate image.
943 #This "for" loop might be integrated with the previous one
944 #In case this integration is made, the VNFCDict might become a VNFClist.
945 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
946 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
948 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
949 image_dict
['universal_name']=vnfc
.get('image name')
950 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
951 image_dict
['location']=vnfc
.get('VNFC image')
952 #image_dict['new_location']=vnfc.get('image location')
953 image_dict
['checksum']=vnfc
.get('image checksum')
954 image_metadata_dict
= vnfc
.get('image metadata', None)
955 image_metadata_str
= None
956 if image_metadata_dict
is not None:
957 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
958 image_dict
['metadata']=image_metadata_str
959 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
960 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
961 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
962 VNFCDict
[vnfc
['name']]["image_id"] = image_id
963 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
964 if vnfc
.get("boot-data"):
965 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
967 # Step 7. Storing the VNF descriptor in the repository
968 if "descriptor" not in vnf_descriptor
["vnf"]:
969 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
971 # Step 8. Adding the VNF to the NFVO DB
972 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
974 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
975 _
, message
= rollback(mydb
, vims
, rollback_list
)
976 if isinstance(e
, db_base_Exception
):
977 error_text
= "Exception at database"
978 elif isinstance(e
, KeyError):
979 error_text
= "KeyError exception "
980 e
.http_code
= HTTP_Internal_Server_Error
982 error_text
= "Exception at VIM"
983 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
984 #logger.error("start_scenario %s", error_text)
985 raise NfvoException(error_text
, e
.http_code
)
988 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
989 #check valid tenant_id
990 check_tenant(mydb
, tenant_id
)
993 if tenant_id
!= "any":
994 where_or
["tenant_id"] = tenant_id
995 where_or
["public"] = True
996 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
999 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
1000 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
1001 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1002 data
={'vnf' : filtered_content
}
1004 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1005 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description', 'boot_data'),
1006 WHERE
={'vnfs.uuid': vnf_id
} )
1008 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1009 # change boot_data into boot-data
1011 if vm
.get("boot_data"):
1012 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1015 data
['vnf']['VNFC'] = content
1016 #TODO: GET all the information from a VNFC and include it in the output.
1019 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1020 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1021 WHERE
={'vnfs.uuid': vnf_id
} )
1022 data
['vnf']['nets'] = content
1024 #GET ip-profile for each net
1025 for net
in data
['vnf']['nets']:
1026 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1027 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1028 WHERE
={'net_id': net
["uuid"]} )
1029 if len(ipprofiles
)==1:
1030 net
["ip_profile"] = ipprofiles
[0]
1031 elif len(ipprofiles
)>1:
1032 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
1035 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1037 #GET External Interfaces
1038 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1039 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1040 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1041 WHERE
={'vnfs.uuid': vnf_id
},
1042 WHERE_NOT
={'interfaces.external_name': None} )
1044 data
['vnf']['external-connections'] = content
1049 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1050 # Check tenant exist
1051 if tenant_id
!= "any":
1052 check_tenant(mydb
, tenant_id
)
1053 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1054 vims
= get_vim(mydb
, tenant_id
)
1058 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1060 if tenant_id
!= "any":
1061 where_or
["tenant_id"] = tenant_id
1062 where_or
["public"] = True
1063 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1064 vnf_id
= vnf
["uuid"]
1066 # "Getting the list of flavors and tenants of the VNF"
1067 flavorList
= get_flavorlist(mydb
, vnf_id
)
1068 if len(flavorList
)==0:
1069 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1071 imageList
= get_imagelist(mydb
, vnf_id
)
1072 if len(imageList
)==0:
1073 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1075 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1077 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1080 for flavor
in flavorList
:
1081 #check if flavor is used by other vnf
1083 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1085 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1087 #flavor not used, must be deleted
1089 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
1090 for flavor_vim
in c
:
1091 if flavor_vim
["datacenter_id"] not in vims
:
1093 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
1095 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
1097 myvim
.delete_flavor(flavor_vim
["vim_id"])
1098 except vimconn
.vimconnNotFoundException
as e
:
1099 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
1100 except vimconn
.vimconnException
as e
:
1101 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1102 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1103 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
1104 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1105 mydb
.delete_row_by_id('flavors', flavor
)
1106 except db_base_Exception
as e
:
1107 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1108 undeletedItems
.append("flavor %s" % flavor
)
1111 for image
in imageList
:
1113 #check if image is used by other vnf
1114 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1116 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1118 #image not used, must be deleted
1120 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1122 if image_vim
["datacenter_id"] not in vims
:
1124 if image_vim
['created']=='false': #skip this image because not created by openmano
1126 myvim
=vims
[ image_vim
["datacenter_id"] ]
1128 myvim
.delete_image(image_vim
["vim_id"])
1129 except vimconn
.vimconnNotFoundException
as e
:
1130 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1131 except vimconn
.vimconnException
as e
:
1132 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1133 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1134 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1135 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1136 mydb
.delete_row_by_id('images', image
)
1137 except db_base_Exception
as e
:
1138 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1139 undeletedItems
.append("image %s" % image
)
1141 return vnf_id
+ " " + vnf
["name"]
1143 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1146 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1147 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1151 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1152 myvim
= vims
.values()[0]
1153 result
,servers
= myvim
.get_hosts_info()
1155 return result
, servers
1156 topology
= {'name':myvim
['name'] , 'servers': servers
}
1157 return result
, topology
1160 def get_hosts(mydb
, nfvo_tenant_id
):
1161 vims
= get_vim(mydb
, nfvo_tenant_id
)
1163 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1165 #print "nfvo.datacenter_action() error. Several datacenters found"
1166 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1167 myvim
= vims
.values()[0]
1169 hosts
= myvim
.get_hosts()
1170 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1172 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1174 server
={'name':host
['name'], 'vms':[]}
1175 for vm
in host
['instances']:
1176 #get internal name and model
1178 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1179 WHERE
={'vim_vm_id':vm
['id']} )
1181 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1183 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1185 except db_base_Exception
as e
:
1186 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1187 datacenter
['Datacenters'][0]['servers'].append(server
)
1188 #return -400, "en construccion"
1190 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1192 except vimconn
.vimconnException
as e
:
1193 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1196 def new_scenario(mydb
, tenant_id
, topo
):
1198 # result, vims = get_vim(mydb, tenant_id)
1200 # return result, vims
1202 if tenant_id
!= "any":
1203 check_tenant(mydb
, tenant_id
)
1204 if "tenant_id" in topo
:
1205 if topo
["tenant_id"] != tenant_id
:
1206 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1211 #1.1: get VNFs and external_networks (other_nets).
1213 other_nets
={} #external_networks, bridge_networks and data_networkds
1214 nodes
= topo
['topology']['nodes']
1215 for k
in nodes
.keys():
1216 if nodes
[k
]['type'] == 'VNF':
1218 vnfs
[k
]['ifaces'] = {}
1219 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1220 other_nets
[k
] = nodes
[k
]
1221 other_nets
[k
]['external']=True
1222 elif nodes
[k
]['type'] == 'network':
1223 other_nets
[k
] = nodes
[k
]
1224 other_nets
[k
]['external']=False
1227 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1228 for name
,vnf
in vnfs
.items():
1230 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1232 error_pos
= "'topology':'nodes':'" + name
+ "'"
1234 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1235 where
['uuid'] = vnf
['vnf_id']
1236 if 'VNF model' in vnf
:
1237 error_text
+= " 'VNF model' " + vnf
['VNF model']
1238 where
['name'] = vnf
['VNF model']
1240 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1242 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1248 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1250 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1251 vnf
['uuid']=vnf_db
[0]['uuid']
1252 vnf
['description']=vnf_db
[0]['description']
1253 #get external interfaces
1254 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1255 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1256 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1257 for ext_iface
in ext_ifaces
:
1258 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1260 #1.4 get list of connections
1261 conections
= topo
['topology']['connections']
1262 conections_list
= []
1263 conections_list_name
= []
1264 for k
in conections
.keys():
1265 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1266 ifaces_list
= conections
[k
]['nodes'].items()
1267 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1269 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1270 for k2
in conection_pair_list
:
1273 con_type
= conections
[k
].get("type", "link")
1274 if con_type
!= "link":
1276 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1277 other_nets
[k
] = {'external': False}
1278 if conections
[k
].get("graph"):
1279 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1280 ifaces_list
.append( (k
, None) )
1283 if con_type
== "external_network":
1284 other_nets
[k
]['external'] = True
1285 if conections
[k
].get("model"):
1286 other_nets
[k
]["model"] = conections
[k
]["model"]
1288 other_nets
[k
]["model"] = k
1289 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1290 other_nets
[k
]["model"] = con_type
1292 conections_list_name
.append(k
)
1293 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)
1294 #print set(ifaces_list)
1295 #check valid VNF and iface names
1296 for iface
in ifaces_list
:
1297 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1298 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1299 str(k
), iface
[0]), HTTP_Not_Found
)
1300 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1301 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1302 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1304 #1.5 unify connections from the pair list to a consolidated list
1306 while index
< len(conections_list
):
1308 while index2
< len(conections_list
):
1309 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1310 conections_list
[index
] |
= conections_list
[index2
]
1311 del conections_list
[index2
]
1312 del conections_list_name
[index2
]
1315 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1317 #for k in conections_list:
1322 #1.6 Delete non external nets
1323 # for k in other_nets.keys():
1324 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1325 # for con in conections_list:
1327 # for index in range(0,len(con)):
1328 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1329 # for index in delete_indexes:
1332 #1.7: Check external_ports are present at database table datacenter_nets
1333 for k
,net
in other_nets
.items():
1334 error_pos
= "'topology':'nodes':'" + k
+ "'"
1335 if net
['external']==False:
1336 if 'name' not in net
:
1338 if 'model' not in net
:
1339 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1340 if net
['model']=='bridge_net':
1341 net
['type']='bridge';
1342 elif net
['model']=='dataplane_net':
1345 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1347 #IF we do not want to check that external network exist at datacenter
1352 # if 'net_id' in net:
1353 # error_text += " 'net_id' " + net['net_id']
1354 # WHERE_['uuid'] = net['net_id']
1355 # if 'model' in net:
1356 # error_text += " 'model' " + net['model']
1357 # WHERE_['name'] = net['model']
1358 # if len(WHERE_) == 0:
1359 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1360 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1361 # FROM='datacenter_nets', WHERE=WHERE_ )
1363 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1365 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1366 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1368 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1369 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1370 # other_nets[k].update(net_db[0])
1373 net_nb
=0 #Number of nets
1374 for con
in conections_list
:
1375 #check if this is connected to a external net
1379 for index
in range(0,len(con
)):
1380 #check if this is connected to a external net
1381 for net_key
in other_nets
.keys():
1382 if con
[index
][0]==net_key
:
1383 if other_net_index
>=0:
1384 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1385 #print "nfvo.new_scenario " + error_text
1386 raise NfvoException(error_text
, HTTP_Bad_Request
)
1388 other_net_index
= index
1389 net_target
= net_key
1391 #print "other_net_index", other_net_index
1393 if other_net_index
>=0:
1394 del con
[other_net_index
]
1395 #IF we do not want to check that external network exist at datacenter
1396 if other_nets
[net_target
]['external'] :
1397 if "name" not in other_nets
[net_target
]:
1398 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1399 if other_nets
[net_target
]["type"] == "external_network":
1400 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1401 other_nets
[net_target
]["type"] = "data"
1403 other_nets
[net_target
]["type"] = "bridge"
1405 # if other_nets[net_target]['external'] :
1406 # 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
1407 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1408 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1409 # print "nfvo.new_scenario " + error_text
1410 # return -HTTP_Bad_Request, error_text
1413 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1416 net_type_bridge
=False
1418 net_target
= "__-__net"+str(net_nb
)
1419 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1420 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1423 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1424 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1425 if iface_type
=='mgmt' or iface_type
=='bridge':
1426 net_type_bridge
= True
1428 net_type_data
= True
1429 if net_type_bridge
and net_type_data
:
1430 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1431 #print "nfvo.new_scenario " + error_text
1432 raise NfvoException(error_text
, HTTP_Bad_Request
)
1433 elif net_type_bridge
:
1436 type_
='data' if len(con
)>2 else 'ptp'
1437 net_list
[net_target
]['type'] = type_
1440 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1441 #print "nfvo.new_scenario " + error_text
1443 raise NfvoException(error_text
, HTTP_Bad_Request
)
1445 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1446 #1.8.1 obtain management net
1447 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1448 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1449 #1.8.2 check all interfaces from all vnfs
1451 add_mgmt_net
= False
1452 for vnf
in vnfs
.values():
1453 for iface
in vnf
['ifaces'].values():
1454 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1455 #iface not connected
1456 iface
['net_key'] = 'mgmt'
1458 if add_mgmt_net
and 'mgmt' not in net_list
:
1459 net_list
['mgmt']=mgmt_net
[0]
1460 net_list
['mgmt']['external']=True
1461 net_list
['mgmt']['graph']={'visible':False}
1463 net_list
.update(other_nets
)
1465 #print 'net_list', net_list
1470 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1471 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1472 'tenant_id':tenant_id
, 'name':topo
['name'],
1473 'description':topo
.get('description',topo
['name']),
1474 'public': topo
.get('public', False)
1480 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
1481 """ This creates a new scenario for version 0.2 and 0.3"""
1482 scenario
= scenario_dict
["scenario"]
1483 if tenant_id
!= "any":
1484 check_tenant(mydb
, tenant_id
)
1485 if "tenant_id" in scenario
:
1486 if scenario
["tenant_id"] != tenant_id
:
1487 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1488 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1489 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1493 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
1494 for name
,vnf
in scenario
["vnfs"].iteritems():
1496 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1498 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1500 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1501 where
['uuid'] = vnf
['vnf_id']
1502 if 'vnf_name' in vnf
:
1503 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1504 where
['name'] = vnf
['vnf_name']
1506 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1507 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
1512 if len(vnf_db
) == 0:
1513 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1514 elif len(vnf_db
) > 1:
1515 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1516 vnf
['uuid'] = vnf_db
[0]['uuid']
1517 vnf
['description'] = vnf_db
[0]['description']
1519 # get external interfaces
1520 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
1521 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1522 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name': None} )
1523 for ext_iface
in ext_ifaces
:
1524 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
1525 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1527 # 2: Insert net_key and ip_address at every vnf interface
1528 for net_name
, net
in scenario
["networks"].items():
1529 net_type_bridge
= False
1530 net_type_data
= False
1531 for iface_dict
in net
["interfaces"]:
1532 if version
== "0.2":
1533 temp_dict
= iface_dict
1535 elif version
== "0.3":
1536 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
1537 ip_address
= iface_dict
.get('ip_address', None)
1538 for vnf
, iface
in temp_dict
.items():
1539 if vnf
not in scenario
["vnfs"]:
1540 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
1542 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1543 raise NfvoException(error_text
, HTTP_Not_Found
)
1544 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1545 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
1546 .format(net_name
, iface
)
1547 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1548 raise NfvoException(error_text
, HTTP_Bad_Request
)
1549 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1550 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
1551 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1552 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1553 raise NfvoException(error_text
, HTTP_Bad_Request
)
1554 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1555 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
1556 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1557 if iface_type
== 'mgmt' or iface_type
== 'bridge':
1558 net_type_bridge
= True
1560 net_type_data
= True
1562 if net_type_bridge
and net_type_data
:
1563 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
1565 # logger.debug("nfvo.new_scenario " + error_text)
1566 raise NfvoException(error_text
, HTTP_Bad_Request
)
1567 elif net_type_bridge
:
1570 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
1572 if net
.get("implementation"): # for v0.3
1573 if type_
== "bridge" and net
["implementation"] == "underlay":
1574 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
1575 "'network':'{}'".format(net_name
)
1576 # logger.debug(error_text)
1577 raise NfvoException(error_text
, HTTP_Bad_Request
)
1578 elif type_
!= "bridge" and net
["implementation"] == "overlay":
1579 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
1580 "'network':'{}'".format(net_name
)
1581 # logger.debug(error_text)
1582 raise NfvoException(error_text
, HTTP_Bad_Request
)
1583 net
.pop("implementation")
1584 if "type" in net
and version
== "0.3": # for v0.3
1585 if type_
== "data" and net
["type"] == "e-line":
1586 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
1587 "'e-line' at 'network':'{}'".format(net_name
)
1588 # logger.debug(error_text)
1589 raise NfvoException(error_text
, HTTP_Bad_Request
)
1590 elif type_
== "ptp" and net
["type"] == "e-lan":
1594 net
['name'] = net_name
1595 net
['external'] = net
.get('external', False)
1597 # 3: insert at database
1598 scenario
["nets"] = scenario
["networks"]
1599 scenario
['tenant_id'] = tenant_id
1600 scenario_id
= mydb
.new_scenario(scenario
)
1604 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1605 data
["uuid"] = scenario_id
1606 data
["tenant_id"] = tenant_id
1607 c
= mydb
.edit_scenario( data
)
1611 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1612 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1613 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
1614 vims
= {datacenter_id
: myvim
}
1615 myvim_tenant
= myvim
['tenant_id']
1616 datacenter_name
= myvim
['name']
1620 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1621 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1622 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
1623 scenarioDict
['datacenter_id'] = datacenter_id
1624 #print '================scenarioDict======================='
1625 #print json.dumps(scenarioDict, indent=4)
1626 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1628 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1629 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1631 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1632 auxNetDict
['scenario'] = {}
1634 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1635 for sce_net
in scenarioDict
['nets']:
1636 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1638 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1639 myNetName
= myNetName
[0:255] #limit length
1640 myNetType
= sce_net
['type']
1642 myNetDict
["name"] = myNetName
1643 myNetDict
["type"] = myNetType
1644 myNetDict
["tenant_id"] = myvim_tenant
1645 myNetIPProfile
= sce_net
.get('ip_profile', None)
1647 #We should use the dictionary as input parameter for new_network
1649 if not sce_net
["external"]:
1650 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1651 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1652 sce_net
['vim_id'] = network_id
1653 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1654 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1655 sce_net
["created"] = True
1657 if sce_net
['vim_id'] == None:
1658 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1659 _
, message
= rollback(mydb
, vims
, rollbackList
)
1660 logger
.error("nfvo.start_scenario: %s", error_text
)
1661 raise NfvoException(error_text
, HTTP_Bad_Request
)
1662 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1663 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1665 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1666 #For each vnf net, we create it and we add it to instanceNetlist.
1667 for sce_vnf
in scenarioDict
['vnfs']:
1668 for net
in sce_vnf
['nets']:
1669 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1671 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1672 myNetName
= myNetName
[0:255] #limit length
1673 myNetType
= net
['type']
1675 myNetDict
["name"] = myNetName
1676 myNetDict
["type"] = myNetType
1677 myNetDict
["tenant_id"] = myvim_tenant
1678 myNetIPProfile
= net
.get('ip_profile', None)
1681 #We should use the dictionary as input parameter for new_network
1682 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1683 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1684 net
['vim_id'] = network_id
1685 if sce_vnf
['uuid'] not in auxNetDict
:
1686 auxNetDict
[sce_vnf
['uuid']] = {}
1687 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1688 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1689 net
["created"] = True
1691 #print "auxNetDict:"
1692 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1694 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1695 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1697 for sce_vnf
in scenarioDict
['vnfs']:
1698 for vm
in sce_vnf
['vms']:
1701 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1702 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
1703 #myVMDict['description'] = vm['description']
1704 myVMDict
['description'] = myVMDict
['name'][0:99]
1706 myVMDict
['start'] = "no"
1707 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1708 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1710 #create image at vim in case it not exist
1711 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1712 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1713 vm
['vim_image_id'] = image_id
1715 #create flavor at vim in case it not exist
1716 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1717 if flavor_dict
['extended']!=None:
1718 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1719 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1720 vm
['vim_flavor_id'] = flavor_id
1723 myVMDict
['imageRef'] = vm
['vim_image_id']
1724 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1725 myVMDict
['networks'] = []
1726 for iface
in vm
['interfaces']:
1728 if iface
['type']=="data":
1729 netDict
['type'] = iface
['model']
1730 elif "model" in iface
and iface
["model"]!=None:
1731 netDict
['model']=iface
['model']
1732 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1733 #discover type of interface looking at flavor
1734 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1735 for flavor_iface
in numa
.get('interfaces',[]):
1736 if flavor_iface
.get('name') == iface
['internal_name']:
1737 if flavor_iface
['dedicated'] == 'yes':
1738 netDict
['type']="PF" #passthrough
1739 elif flavor_iface
['dedicated'] == 'no':
1740 netDict
['type']="VF" #siov
1741 elif flavor_iface
['dedicated'] == 'yes:sriov':
1742 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1743 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1745 netDict
["use"]=iface
['type']
1746 if netDict
["use"]=="data" and not netDict
.get("type"):
1747 #print "netDict", netDict
1748 #print "iface", iface
1749 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'])
1750 if flavor_dict
.get('extended')==None:
1751 raise NfvoException(e_text
+ "After database migration some information is not available. \
1752 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1754 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1755 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1756 netDict
["type"]="virtual"
1757 if "vpci" in iface
and iface
["vpci"] is not None:
1758 netDict
['vpci'] = iface
['vpci']
1759 if "mac" in iface
and iface
["mac"] is not None:
1760 netDict
['mac_address'] = iface
['mac']
1761 if "port-security" in iface
and iface
["port-security"] is not None:
1762 netDict
['port_security'] = iface
['port-security']
1763 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
1764 netDict
['floating_ip'] = iface
['floating-ip']
1765 netDict
['name'] = iface
['internal_name']
1766 if iface
['net_id'] is None:
1767 for vnf_iface
in sce_vnf
["interfaces"]:
1770 if vnf_iface
['interface_id']==iface
['uuid']:
1771 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1774 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1775 #skip bridge ifaces not connected to any net
1776 #if 'net_id' not in netDict or netDict['net_id']==None:
1778 myVMDict
['networks'].append(netDict
)
1779 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1780 #print myVMDict['name']
1781 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1782 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1783 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1784 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1785 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1786 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1787 vm
['vim_id'] = vm_id
1788 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1789 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1790 for net
in myVMDict
['networks']:
1792 for iface
in vm
['interfaces']:
1793 if net
["name"]==iface
["internal_name"]:
1794 iface
["vim_id"]=net
["vim_id"]
1797 logger
.debug("start scenario Deployment done")
1798 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1799 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1800 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1801 return mydb
.get_instance_scenario(instance_id
)
1803 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1804 _
, message
= rollback(mydb
, vims
, rollbackList
)
1805 if isinstance(e
, db_base_Exception
):
1806 error_text
= "Exception at database"
1808 error_text
= "Exception at VIM"
1809 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1810 #logger.error("start_scenario %s", error_text)
1811 raise NfvoException(error_text
, e
.http_code
)
1814 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
1815 ''' join the cloud config information into cloud_config_preserve.
1816 In case of conflict cloud_config_preserve preserves
1819 if not cloud_config_preserve
and not cloud_config
:
1822 new_cloud_config
= {"key-pairs":[], "users":[]}
1824 if cloud_config_preserve
:
1825 for key
in cloud_config_preserve
.get("key-pairs", () ):
1826 if key
not in new_cloud_config
["key-pairs"]:
1827 new_cloud_config
["key-pairs"].append(key
)
1829 for key
in cloud_config
.get("key-pairs", () ):
1830 if key
not in new_cloud_config
["key-pairs"]:
1831 new_cloud_config
["key-pairs"].append(key
)
1832 if not new_cloud_config
["key-pairs"]:
1833 del new_cloud_config
["key-pairs"]
1837 new_cloud_config
["users"] += cloud_config
.get("users", () )
1838 if cloud_config_preserve
:
1839 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
1840 index_to_delete
= []
1841 users
= new_cloud_config
.get("users", [])
1842 for index0
in range(0,len(users
)):
1843 if index0
in index_to_delete
:
1845 for index1
in range(index0
+1,len(users
)):
1846 if index1
in index_to_delete
:
1848 if users
[index0
]["name"] == users
[index1
]["name"]:
1849 index_to_delete
.append(index1
)
1850 for key
in users
[index1
].get("key-pairs",()):
1851 if "key-pairs" not in users
[index0
]:
1852 users
[index0
]["key-pairs"] = [key
]
1853 elif key
not in users
[index0
]["key-pairs"]:
1854 users
[index0
]["key-pairs"].append(key
)
1855 index_to_delete
.sort(reverse
=True)
1856 for index
in index_to_delete
:
1858 if not new_cloud_config
["users"]:
1859 del new_cloud_config
["users"]
1862 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
1863 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
1864 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
1865 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
1868 if cloud_config
and cloud_config
.get("user-data") != None:
1869 new_cloud_config
["user-data"] = cloud_config
["user-data"]
1870 if cloud_config_preserve
and cloud_config_preserve
.get("user-data") != None:
1871 new_cloud_config
["user-data"] = cloud_config_preserve
["user-data"]
1874 new_cloud_config
["config-files"] = []
1875 if cloud_config
and cloud_config
.get("config-files") != None:
1876 new_cloud_config
["config-files"] += cloud_config
["config-files"]
1877 if cloud_config_preserve
:
1878 for file in cloud_config_preserve
.get("config-files", ()):
1879 for index
in range(0, len(new_cloud_config
["config-files"])):
1880 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
1881 new_cloud_config
["config-files"][index
] = file
1884 new_cloud_config
["config-files"].append(file)
1885 if not new_cloud_config
["config-files"]:
1886 del new_cloud_config
["config-files"]
1887 return new_cloud_config
1890 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
1891 datacenter_id
= None
1892 datacenter_name
= None
1895 if datacenter_tenant_id
:
1896 thread_id
= datacenter_tenant_id
1897 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
1899 where_
={"td.nfvo_tenant_id": tenant_id
}
1900 if datacenter_id_name
:
1901 if utils
.check_valid_uuid(datacenter_id_name
):
1902 datacenter_id
= datacenter_id_name
1903 where_
["dt.datacenter_id"] = datacenter_id
1905 datacenter_name
= datacenter_id_name
1906 where_
["d.name"] = datacenter_name
1907 if datacenter_tenant_id
:
1908 where_
["dt.uuid"] = datacenter_tenant_id
1909 datacenters
= mydb
.get_rows(
1910 SELECT
=("dt.uuid as datacenter_tenant_id",),
1911 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
1912 "join datacenters as d on d.uuid=dt.datacenter_id",
1914 if len(datacenters
) > 1:
1915 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1917 thread_id
= datacenters
[0]["datacenter_tenant_id"]
1918 thread
= vim_threads
["running"].get(thread_id
)
1920 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1921 return thread_id
, thread
1922 except db_base_Exception
as e
:
1923 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
1925 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1926 datacenter_id
= None
1927 datacenter_name
= None
1928 if datacenter_id_name
:
1929 if utils
.check_valid_uuid(datacenter_id_name
):
1930 datacenter_id
= datacenter_id_name
1932 datacenter_name
= datacenter_id_name
1933 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1935 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1937 #print "nfvo.datacenter_action() error. Several datacenters found"
1938 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1939 return vims
.keys()[0], vims
.values()[0]
1943 '''Takes dict d and updates it with the values in dict u.'''
1944 '''It merges all depth levels'''
1945 for k
, v
in u
.iteritems():
1946 if isinstance(v
, collections
.Mapping
):
1947 r
= update(d
.get(k
, {}), v
)
1954 def create_instance(mydb
, tenant_id
, instance_dict
):
1955 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1956 # logger.debug("Creating instance...")
1957 scenario
= instance_dict
["scenario"]
1959 #find main datacenter
1961 myvim_threads_id
= {}
1964 datacenter
= instance_dict
.get("datacenter")
1965 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1966 myvims
[default_datacenter_id
] = vim
1967 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
1968 tasks_to_launch
[myvim_threads_id
[default_datacenter_id
]] = []
1969 #myvim_tenant = myvim['tenant_id']
1970 # default_datacenter_name = vim['name']
1973 #print "Checking that the scenario exists and getting the scenario dictionary"
1974 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1976 #logger.debug(">>>>>>> Dictionaries before merging")
1977 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1978 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1980 scenarioDict
['datacenter_id'] = default_datacenter_id
1982 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1983 auxNetDict
['scenario'] = {}
1985 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1986 instance_name
= instance_dict
["name"]
1987 instance_description
= instance_dict
.get("description")
1989 # 0 check correct parameters
1990 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1992 for scenario_net
in scenarioDict
['nets']:
1993 if net_name
== scenario_net
["name"]:
1997 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1998 if "sites" not in net_instance_desc
:
1999 net_instance_desc
["sites"] = [ {} ]
2000 site_without_datacenter_field
= False
2001 for site
in net_instance_desc
["sites"]:
2002 if site
.get("datacenter"):
2003 if site
["datacenter"] not in myvims
:
2004 #Add this datacenter to myvims
2005 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
2007 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
2008 tasks_to_launch
[myvim_threads_id
[d
]] = []
2009 site
["datacenter"] = d
#change name to id
2011 if site_without_datacenter_field
:
2012 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
2013 site_without_datacenter_field
= True
2014 site
["datacenter"] = default_datacenter_id
#change name to id
2016 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
2018 for scenario_vnf
in scenarioDict
['vnfs']:
2019 if vnf_name
== scenario_vnf
['name']:
2023 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
2024 if "datacenter" in vnf_instance_desc
:
2025 # Add this datacenter to myvims
2026 if vnf_instance_desc
["datacenter"] not in myvims
:
2027 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2029 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2030 tasks_to_launch
[myvim_threads_id
[d
]] = []
2031 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2033 #0.1 parse cloud-config parameters
2034 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2036 #0.2 merge instance information into scenario
2037 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2038 #However, this is not possible yet.
2039 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2040 for scenario_net
in scenarioDict
['nets']:
2041 if net_name
== scenario_net
["name"]:
2042 if 'ip-profile' in net_instance_desc
:
2043 ipprofile
= net_instance_desc
['ip-profile']
2044 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
2045 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
2046 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
2047 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
2048 if 'dhcp' in ipprofile
:
2049 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
2050 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
2051 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
2052 del ipprofile
['dhcp']
2053 if 'ip_profile' not in scenario_net
:
2054 scenario_net
['ip_profile'] = ipprofile
2056 update(scenario_net
['ip_profile'],ipprofile
)
2057 for interface
in net_instance_desc
.get('interfaces', () ):
2058 if 'ip_address' in interface
:
2059 for vnf
in scenarioDict
['vnfs']:
2060 if interface
['vnf'] == vnf
['name']:
2061 for vnf_interface
in vnf
['interfaces']:
2062 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2063 vnf_interface
['ip_address']=interface
['ip_address']
2065 #logger.debug(">>>>>>>> Merged dictionary")
2066 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
2069 # 1. Creating new nets (sce_nets) in the VIM"
2070 for sce_net
in scenarioDict
['nets']:
2071 sce_net
["vim_id_sites"]={}
2072 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
2073 net_name
= descriptor_net
.get("vim-network-name")
2074 auxNetDict
['scenario'][sce_net
['uuid']] = {}
2076 sites
= descriptor_net
.get("sites", [ {} ])
2078 if site
.get("datacenter"):
2079 vim
= myvims
[ site
["datacenter"] ]
2080 datacenter_id
= site
["datacenter"]
2081 myvim_thread_id
= myvim_threads_id
[ site
["datacenter"] ]
2083 vim
= myvims
[ default_datacenter_id
]
2084 datacenter_id
= default_datacenter_id
2085 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2086 net_type
= sce_net
['type']
2087 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
2088 if sce_net
["external"]:
2090 net_name
= sce_net
["name"]
2091 if "netmap-use" in site
or "netmap-create" in site
:
2092 create_network
= False
2093 lookfor_network
= False
2094 if "netmap-use" in site
:
2095 lookfor_network
= True
2096 if utils
.check_valid_uuid(site
["netmap-use"]):
2097 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2098 lookfor_filter
["id"] = site
["netmap-use"]
2100 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2101 lookfor_filter
["name"] = site
["netmap-use"]
2102 if "netmap-create" in site
:
2103 create_network
= True
2104 net_vim_name
= net_name
2105 if site
["netmap-create"]:
2106 net_vim_name
= site
["netmap-create"]
2108 elif sce_net
['vim_id'] != None:
2109 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
2110 create_network
= False
2111 lookfor_network
= True
2112 lookfor_filter
["id"] = sce_net
['vim_id']
2113 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
2114 #look for network at datacenter and return error
2116 #There is not a netmap, look at datacenter for a net with this name and create if not found
2117 create_network
= True
2118 lookfor_network
= True
2119 lookfor_filter
["name"] = sce_net
["name"]
2120 net_vim_name
= sce_net
["name"]
2121 filter_text
= "scenario name '%s'" % sce_net
["name"]
2124 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
2125 net_name
= net_name
[:255] #limit length
2126 net_vim_name
= net_name
2127 create_network
= True
2128 lookfor_network
= False
2131 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
2132 if len(vim_nets
) > 1:
2133 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2134 elif len(vim_nets
) == 0:
2135 if not create_network
:
2136 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2138 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
2139 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
2140 create_network
= False
2142 #if network is not external
2143 task
= new_task("new-net", (net_vim_name
, net_type
, sce_net
.get('ip_profile',None)))
2144 task_id
= task
["id"]
2145 instance_tasks
[task_id
] = task
2146 tasks_to_launch
[myvim_thread_id
].append(task
)
2147 #network_id = vim.new_network(net_vim_name, net_type, sce_net.get('ip_profile',None))
2148 sce_net
["vim_id_sites"][datacenter_id
] = task_id
2149 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = task_id
2150 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':task_id
})
2151 sce_net
["created"] = True
2153 # 2. Creating new nets (vnf internal nets) in the VIM"
2154 #For each vnf net, we create it and we add it to instanceNetlist.
2155 for sce_vnf
in scenarioDict
['vnfs']:
2156 for net
in sce_vnf
['nets']:
2157 if sce_vnf
.get("datacenter"):
2158 vim
= myvims
[ sce_vnf
["datacenter"] ]
2159 datacenter_id
= sce_vnf
["datacenter"]
2160 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"]]
2162 vim
= myvims
[ default_datacenter_id
]
2163 datacenter_id
= default_datacenter_id
2164 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2165 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
2166 net_name
= descriptor_net
.get("name")
2168 net_name
= "%s.%s" %(instance_name
, net
["name"])
2169 net_name
= net_name
[:255] #limit length
2170 net_type
= net
['type']
2171 task
= new_task("new-net", (net_name
, net_type
, net
.get('ip_profile',None)))
2172 task_id
= task
["id"]
2173 instance_tasks
[task_id
] = task
2174 tasks_to_launch
[myvim_thread_id
].append(task
)
2175 # network_id = vim.new_network(net_name, net_type, net.get('ip_profile',None))
2176 net
['vim_id'] = task_id
2177 if sce_vnf
['uuid'] not in auxNetDict
:
2178 auxNetDict
[sce_vnf
['uuid']] = {}
2179 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = task_id
2180 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':task_id
})
2181 net
["created"] = True
2184 #print "auxNetDict:"
2185 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2187 # 3. Creating new vm instances in the VIM
2188 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2189 for sce_vnf
in scenarioDict
['vnfs']:
2190 if sce_vnf
.get("datacenter"):
2191 vim
= myvims
[ sce_vnf
["datacenter"] ]
2192 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"] ]
2193 datacenter_id
= sce_vnf
["datacenter"]
2195 vim
= myvims
[ default_datacenter_id
]
2196 myvim_thread_id
= myvim_threads_id
[ default_datacenter_id
]
2197 datacenter_id
= default_datacenter_id
2198 sce_vnf
["datacenter_id"] = datacenter_id
2200 for vm
in sce_vnf
['vms']:
2203 myVMDict
['name'] = "{}.{}.{}".format(instance_name
,sce_vnf
['name'],chr(96+i
))
2204 myVMDict
['description'] = myVMDict
['name'][0:99]
2206 # myVMDict['start'] = "no"
2207 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2208 #create image at vim in case it not exist
2209 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2210 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2211 vm
['vim_image_id'] = image_id
2213 #create flavor at vim in case it not exist
2214 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2215 if flavor_dict
['extended']!=None:
2216 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2217 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
2219 #Obtain information for additional disks
2220 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
2221 if not extended_flavor_dict
:
2222 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
2225 #extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
2226 myVMDict
['disks'] = None
2227 extended_info
= extended_flavor_dict
[0]['extended']
2228 if extended_info
!= None:
2229 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
2230 if 'disks' in extended_flavor_dict_yaml
:
2231 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
2233 vm
['vim_flavor_id'] = flavor_id
2234 myVMDict
['imageRef'] = vm
['vim_image_id']
2235 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2236 myVMDict
['networks'] = []
2238 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
2239 for iface
in vm
['interfaces']:
2241 if iface
['type']=="data":
2242 netDict
['type'] = iface
['model']
2243 elif "model" in iface
and iface
["model"]!=None:
2244 netDict
['model']=iface
['model']
2245 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2246 #discover type of interface looking at flavor
2247 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2248 for flavor_iface
in numa
.get('interfaces',[]):
2249 if flavor_iface
.get('name') == iface
['internal_name']:
2250 if flavor_iface
['dedicated'] == 'yes':
2251 netDict
['type']="PF" #passthrough
2252 elif flavor_iface
['dedicated'] == 'no':
2253 netDict
['type']="VF" #siov
2254 elif flavor_iface
['dedicated'] == 'yes:sriov':
2255 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2256 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2258 netDict
["use"]=iface
['type']
2259 if netDict
["use"]=="data" and not netDict
.get("type"):
2260 #print "netDict", netDict
2261 #print "iface", iface
2262 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'])
2263 if flavor_dict
.get('extended')==None:
2264 raise NfvoException(e_text
+ "After database migration some information is not available. \
2265 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2267 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2268 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2269 netDict
["type"]="virtual"
2270 if "vpci" in iface
and iface
["vpci"] is not None:
2271 netDict
['vpci'] = iface
['vpci']
2272 if "mac" in iface
and iface
["mac"] is not None:
2273 netDict
['mac_address'] = iface
['mac']
2274 if "port-security" in iface
and iface
["port-security"] is not None:
2275 netDict
['port_security'] = iface
['port-security']
2276 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2277 netDict
['floating_ip'] = iface
['floating-ip']
2278 netDict
['name'] = iface
['internal_name']
2279 if iface
['net_id'] is None:
2280 for vnf_iface
in sce_vnf
["interfaces"]:
2283 if vnf_iface
['interface_id']==iface
['uuid']:
2284 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
2287 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2288 if netDict
.get('net_id') and is_task_id(netDict
['net_id']):
2289 task_depends
[netDict
['net_id']] = instance_tasks
[netDict
['net_id']]
2290 #skip bridge ifaces not connected to any net
2291 #if 'net_id' not in netDict or netDict['net_id']==None:
2293 myVMDict
['networks'].append(netDict
)
2294 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2295 #print myVMDict['name']
2296 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2297 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2298 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2299 if vm
.get("boot_data"):
2300 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
2302 cloud_config_vm
= cloud_config
2303 task
= new_task("new-vm", (myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2304 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2305 cloud_config_vm
, myVMDict
['disks']), depends
=task_depends
)
2306 instance_tasks
[task
["id"]] = task
2307 tasks_to_launch
[myvim_thread_id
].append(task
)
2309 vm
['vim_id'] = vm_id
2310 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2311 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2312 for net
in myVMDict
['networks']:
2314 for iface
in vm
['interfaces']:
2315 if net
["name"]==iface
["internal_name"]:
2316 iface
["vim_id"]=net
["vim_id"]
2318 scenarioDict
["datacenter2tenant"] = myvim_threads_id
2319 logger
.debug("create_instance Deployment done scenarioDict: %s",
2320 yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False) )
2321 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
2322 for myvim_thread_id
,task_list
in tasks_to_launch
.items():
2323 for task
in task_list
:
2324 vim_threads
["running"][myvim_thread_id
].insert_task(task
)
2326 global_instance_tasks
[instance_id
] = instance_tasks
2327 # Update database with those ended instance_tasks
2328 # for task in instance_tasks.values():
2329 # if task["status"] == "ok":
2330 # if task["name"] == "new-vm":
2331 # mydb.update_rows("instance_vms", UPDATE={"vim_vm_id": task["result"]},
2332 # WHERE={"vim_vm_id": task["id"]})
2333 # elif task["name"] == "new-net":
2334 # mydb.update_rows("instance_nets", UPDATE={"vim_net_id": task["result"]},
2335 # WHERE={"vim_net_id": task["id"]})
2336 return mydb
.get_instance_scenario(instance_id
)
2337 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2338 message
= rollback(mydb
, myvims
, rollbackList
)
2339 if isinstance(e
, db_base_Exception
):
2340 error_text
= "database Exception"
2341 elif isinstance(e
, vimconn
.vimconnException
):
2342 error_text
= "VIM Exception"
2344 error_text
= "Exception"
2345 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2346 #logger.error("create_instance: %s", error_text)
2347 raise NfvoException(error_text
, e
.http_code
)
2350 def delete_instance(mydb
, tenant_id
, instance_id
):
2351 #print "Checking that the instance_id exists and getting the instance dictionary"
2352 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2353 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2354 tenant_id
= instanceDict
["tenant_id"]
2355 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2357 #1. Delete from Database
2358 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2367 for sce_vnf
in instanceDict
['vnfs']:
2368 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2369 if datacenter_key
not in myvims
:
2371 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2372 except NfvoException
as e
:
2373 logger
.error(str(e
))
2375 myvim_threads
[datacenter_key
] = myvim_thread
2376 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2377 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2379 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2380 sce_vnf
["datacenter_tenant_id"]))
2381 myvims
[datacenter_key
] = None
2383 myvims
[datacenter_key
] = vims
.values()[0]
2384 myvim
= myvims
[datacenter_key
]
2385 myvim_thread
= myvim_threads
[datacenter_key
]
2386 for vm
in sce_vnf
['vms']:
2388 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2392 if is_task_id(vm
['vim_vm_id']):
2393 task_id
= vm
['vim_vm_id']
2394 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2396 error_msg
+= "\n VM was scheduled for create, but task {} is not found".format(task_id
)
2399 if old_task
["status"] == "enqueued":
2400 old_task
["status"] = "deleted"
2401 elif old_task
["status"] == "error":
2403 elif old_task
["status"] == "processing":
2404 task
= new_task("del-vm", (task_id
, vm
["interfaces"]), depends
={task_id
: old_task
})
2406 task
= new_task("del-vm", (old_task
["result"], vm
["interfaces"]))
2408 task
= new_task("del-vm", (vm
['vim_vm_id'], vm
["interfaces"]) )
2410 myvim_thread
.insert_task(task
)
2411 except vimconn
.vimconnNotFoundException
as e
:
2412 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2413 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2414 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2415 except vimconn
.vimconnException
as e
:
2416 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2417 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2418 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2422 for net
in instanceDict
['nets']:
2423 if not net
['created']:
2424 continue #skip not created nets
2425 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2426 if datacenter_key
not in myvims
:
2428 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2429 except NfvoException
as e
:
2430 logger
.error(str(e
))
2432 myvim_threads
[datacenter_key
] = myvim_thread
2433 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2434 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2436 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2437 myvims
[datacenter_key
] = None
2439 myvims
[datacenter_key
] = vims
.values()[0]
2440 myvim
= myvims
[datacenter_key
]
2441 myvim_thread
= myvim_threads
[datacenter_key
]
2444 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2448 if is_task_id(net
['vim_net_id']):
2449 task_id
= net
['vim_net_id']
2450 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2452 error_msg
+= "\n NET was scheduled for create, but task {} is not found".format(task_id
)
2455 if old_task
["status"] == "enqueued":
2456 old_task
["status"] = "deleted"
2457 elif old_task
["status"] == "error":
2459 elif old_task
["status"] == "processing":
2460 task
= new_task("del-net", task_id
, depends
={task_id
: old_task
})
2462 task
= new_task("del-net", old_task
["result"])
2464 task
= new_task("del-net", (net
['vim_net_id'], net
['sdn_net_id']))
2466 myvim_thread
.insert_task(task
)
2467 except vimconn
.vimconnNotFoundException
as e
:
2468 error_msg
+= "\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2469 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2470 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2471 except vimconn
.vimconnException
as e
:
2472 error_msg
+= "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'],
2473 net
["datacenter_id"],
2474 e
.http_code
, str(e
))
2475 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2476 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2477 if len(error_msg
) > 0:
2478 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2480 return 'instance ' + message
+ ' deleted'
2483 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2484 '''Refreshes a scenario instance. It modifies instanceDict'''
2486 - 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
2489 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2490 # #print "nfvo.refresh_instance begins"
2491 # #print json.dumps(instanceDict, indent=4)
2493 # #print "Getting the VIM URL and the VIM tenant_id"
2496 # # 1. Getting VIM vm and net list
2497 # vms_updated = [] #List of VM instance uuids in openmano that were updated
2500 # for sce_vnf in instanceDict['vnfs']:
2501 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
2502 # if datacenter_key not in vm_list:
2503 # vm_list[datacenter_key] = []
2504 # if datacenter_key not in myvims:
2505 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
2506 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
2507 # if len(vims) == 0:
2508 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
2509 # myvims[datacenter_key] = None
2511 # myvims[datacenter_key] = vims.values()[0]
2512 # for vm in sce_vnf['vms']:
2513 # vm_list[datacenter_key].append(vm['vim_vm_id'])
2514 # vms_notupdated.append(vm["uuid"])
2516 # nets_updated = [] #List of VM instance uuids in openmano that were updated
2517 # nets_notupdated=[]
2519 # for net in instanceDict['nets']:
2520 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
2521 # if datacenter_key not in net_list:
2522 # net_list[datacenter_key] = []
2523 # if datacenter_key not in myvims:
2524 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
2525 # datacenter_tenant_id=net["datacenter_tenant_id"])
2526 # if len(vims) == 0:
2527 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
2528 # myvims[datacenter_key] = None
2530 # myvims[datacenter_key] = vims.values()[0]
2532 # net_list[datacenter_key].append(net['vim_net_id'])
2533 # nets_notupdated.append(net["uuid"])
2535 # # 1. Getting the status of all VMs
2537 # for datacenter_key in myvims:
2538 # if not vm_list.get(datacenter_key):
2542 # if not myvims[datacenter_key]:
2543 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2546 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
2548 # except vimconn.vimconnException as e:
2549 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2550 # failed_message = str(e)
2552 # for vm in vm_list[datacenter_key]:
2553 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2555 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2556 # for sce_vnf in instanceDict['vnfs']:
2557 # for vm in sce_vnf['vms']:
2558 # vm_id = vm['vim_vm_id']
2559 # interfaces = vm_dict[vm_id].pop('interfaces', [])
2560 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2561 # has_mgmt_iface = False
2562 # for iface in vm["interfaces"]:
2563 # if iface["type"]=="mgmt":
2564 # has_mgmt_iface = True
2565 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
2566 # vm_dict[vm_id]['status'] = "ACTIVE"
2567 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
2568 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
2569 # 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'):
2570 # vm['status'] = vm_dict[vm_id]['status']
2571 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
2572 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
2573 # # 2.1. Update in openmano DB the VMs whose status changed
2575 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
2576 # vms_notupdated.remove(vm["uuid"])
2578 # vms_updated.append(vm["uuid"])
2579 # except db_base_Exception as e:
2580 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2581 # # 2.2. Update in openmano DB the interface VMs
2582 # for interface in interfaces:
2583 # #translate from vim_net_id to instance_net_id
2584 # network_id_list=[]
2585 # for net in instanceDict['nets']:
2586 # if net["vim_net_id"] == interface["vim_net_id"]:
2587 # network_id_list.append(net["uuid"])
2588 # if not network_id_list:
2590 # del interface["vim_net_id"]
2592 # for network_id in network_id_list:
2593 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
2594 # except db_base_Exception as e:
2595 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
2597 # # 3. Getting the status of all nets
2599 # for datacenter_key in myvims:
2600 # if not net_list.get(datacenter_key):
2603 # failed_message = ""
2604 # if not myvims[datacenter_key]:
2605 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2608 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
2610 # except vimconn.vimconnException as e:
2611 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2612 # failed_message = str(e)
2614 # for net in net_list[datacenter_key]:
2615 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2617 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2618 # # TODO: update nets inside a vnf
2619 # for net in instanceDict['nets']:
2620 # net_id = net['vim_net_id']
2621 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
2622 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
2623 # 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'):
2624 # net['status'] = net_dict[net_id]['status']
2625 # net['error_msg'] = net_dict[net_id].get('error_msg')
2626 # net['vim_info'] = net_dict[net_id].get('vim_info')
2627 # # 5.1. Update in openmano DB the nets whose status changed
2629 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
2630 # nets_notupdated.remove(net["uuid"])
2632 # nets_updated.append(net["uuid"])
2633 # except db_base_Exception as e:
2634 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2636 # # Returns appropriate output
2637 # #print "nfvo.refresh_instance finishes"
2638 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2639 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
2640 instance_id
= instanceDict
['uuid']
2641 # if len(vms_notupdated)+len(nets_notupdated)>0:
2642 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
2643 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
2645 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2648 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2649 #print "Checking that the instance_id exists and getting the instance dictionary"
2650 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2651 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2653 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2654 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2656 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2657 myvim
= vims
.values()[0]
2660 input_vnfs
= action_dict
.pop("vnfs", [])
2661 input_vms
= action_dict
.pop("vms", [])
2662 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2666 for sce_vnf
in instanceDict
['vnfs']:
2667 for vm
in sce_vnf
['vms']:
2668 if not action_over_all
:
2669 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2670 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2673 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2674 if "console" in action_dict
:
2675 if not global_config
["http_console_proxy"]:
2676 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2677 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2678 protocol
=data
["protocol"],
2679 ip
= data
["server"],
2680 port
= data
["port"],
2681 suffix
= data
["suffix"]),
2685 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2686 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2687 "description": "this console is only reachable by local interface",
2692 #print "console data", data
2694 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2695 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2696 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2697 protocol
=data
["protocol"],
2698 ip
= global_config
["http_console_host"],
2699 port
= console_thread
.port
,
2700 suffix
= data
["suffix"]),
2704 except NfvoException
as e
:
2705 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2709 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2711 except vimconn
.vimconnException
as e
:
2712 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2715 if vm_ok
==0: #all goes wrong
2721 def create_or_use_console_proxy_thread(console_server
, console_port
):
2722 #look for a non-used port
2723 console_thread_key
= console_server
+ ":" + str(console_port
)
2724 if console_thread_key
in global_config
["console_thread"]:
2725 #global_config["console_thread"][console_thread_key].start_timeout()
2726 return global_config
["console_thread"][console_thread_key
]
2728 for port
in global_config
["console_port_iterator"]():
2729 #print "create_or_use_console_proxy_thread() port:", port
2730 if port
in global_config
["console_ports"]:
2733 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2735 global_config
["console_thread"][console_thread_key
] = clithread
2736 global_config
["console_ports"][port
] = console_thread_key
2738 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2739 #port used, try with onoher
2741 except cli
.ConsoleProxyException
as e
:
2742 raise NfvoException(str(e
), HTTP_Bad_Request
)
2743 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2746 def check_tenant(mydb
, tenant_id
):
2747 '''check that tenant exists at database'''
2748 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2750 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2754 def new_tenant(mydb
, tenant_dict
):
2755 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2759 def delete_tenant(mydb
, tenant
):
2760 #get nfvo_tenant info
2762 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2763 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2764 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2767 def new_datacenter(mydb
, datacenter_descriptor
):
2768 if "config" in datacenter_descriptor
:
2769 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2770 #Check that datacenter-type is correct
2771 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2774 module
= "vimconn_" + datacenter_type
2775 pkg
= __import__("osm_ro." + module
)
2776 vim_conn
= getattr(pkg
, module
)
2777 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
2778 except (IOError, ImportError):
2779 # if module_info and module_info[0]:
2780 # file.close(module_info[0])
2781 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2783 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2784 return datacenter_id
2787 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2788 #obtain data, check that only one exist
2789 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2791 datacenter_id
= datacenter
['uuid']
2792 where
={'uuid': datacenter
['uuid']}
2793 if "config" in datacenter_descriptor
:
2794 if datacenter_descriptor
['config']!=None:
2796 new_config_dict
= datacenter_descriptor
["config"]
2799 for k
in new_config_dict
:
2800 if new_config_dict
[k
]==None:
2803 config_text
= datacenter
.get("config")
2806 config_dict
= yaml
.load(config_text
)
2807 config_dict
.update(new_config_dict
)
2811 except Exception as e
:
2812 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2813 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2814 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2815 return datacenter_id
2818 def delete_datacenter(mydb
, datacenter
):
2819 #get nfvo_tenant info
2820 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2821 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2822 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2825 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):
2826 #get datacenter info
2827 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
, vim_passwd
=vim_password
)
2828 datacenter_name
= myvim
["name"]
2830 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
2832 # get nfvo_tenant info
2833 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2834 if vim_tenant_name
==None:
2835 vim_tenant_name
=tenant_dict
['name']
2837 #check that this association does not exist before
2838 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2839 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2840 if len(tenants_datacenters
)>0:
2841 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2843 vim_tenant_id_exist_atdb
=False
2844 if not create_vim_tenant
:
2845 where_
={"datacenter_id": datacenter_id
}
2846 if vim_tenant_id
!=None:
2847 where_
["vim_tenant_id"] = vim_tenant_id
2848 if vim_tenant_name
!=None:
2849 where_
["vim_tenant_name"] = vim_tenant_name
2850 #check if vim_tenant_id is already at database
2851 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2852 if len(datacenter_tenants_dict
)>=1:
2853 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2854 vim_tenant_id_exist_atdb
=True
2855 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2857 datacenter_tenants_dict
= {}
2858 #insert at table datacenter_tenants
2859 else: #if vim_tenant_id==None:
2860 #create tenant at VIM if not provided
2862 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2863 except vimconn
.vimconnException
as e
:
2864 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2865 datacenter_tenants_dict
= {}
2866 datacenter_tenants_dict
["created"]="true"
2868 #fill datacenter_tenants table
2869 if not vim_tenant_id_exist_atdb
:
2870 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2871 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2872 datacenter_tenants_dict
["user"] = vim_username
2873 datacenter_tenants_dict
["passwd"] = vim_password
2874 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2876 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
2877 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2878 datacenter_tenants_dict
["uuid"] = id_
2880 #fill tenants_datacenters table
2881 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
2882 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
2883 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2885 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
2886 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
2887 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
2888 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
2890 thread_id
= datacenter_tenants_dict
["uuid"]
2891 vim_threads
["running"][thread_id
] = new_thread
2892 return datacenter_id
2895 def edit_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=None, vim_tenant_name
=None,
2896 vim_username
=None, vim_password
=None, config
=None):
2897 #Obtain the data of this datacenter_tenant_id
2898 vim_data
= mydb
.get_rows(
2899 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
2900 "datacenter_tenants.passwd", "datacenter_tenants.config"),
2901 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
2902 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
2903 "tenants_datacenters.datacenter_id": datacenter_id
})
2905 logger
.debug(str(vim_data
))
2906 if len(vim_data
) < 1:
2907 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
2911 v
['config'] = yaml
.load(v
['config'])
2914 v
['vim_tenant_id'] = vim_tenant_id
2916 v
['vim_tenant_name'] = vim_tenant_name
2918 v
['user'] = vim_username
2920 v
['passwd'] = vim_password
2924 v
['config'].update(config
)
2926 logger
.debug(str(v
))
2927 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
2928 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
2929 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
2931 return datacenter_id
2933 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2934 #get datacenter info
2935 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2937 #get nfvo_tenant info
2938 if not tenant_id
or tenant_id
=="any":
2941 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2942 tenant_uuid
= tenant_dict
['uuid']
2944 #check that this association exist before
2945 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2947 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2948 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2949 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2950 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2952 #delete this association
2953 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2955 #get vim_tenant info and deletes
2957 for tenant_datacenter_item
in tenant_datacenter_list
:
2958 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2959 #try to delete vim:tenant
2961 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2962 if vim_tenant_dict
['created']=='true':
2963 #delete tenant at VIM if created by NFVO
2965 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2966 except vimconn
.vimconnException
as e
:
2967 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2968 logger
.warn(warning
)
2969 except db_base_Exception
as e
:
2970 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2971 pass # the error will be caused because dependencies, vim_tenant can not be deleted
2972 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
2973 thread
= vim_threads
["running"][thread_id
]
2974 thread
.insert_task(new_task("exit", None))
2975 vim_threads
["deleting"][thread_id
] = thread
2976 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2979 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2981 #get datacenter info
2982 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2984 if 'net-update' in action_dict
:
2986 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2988 except vimconn
.vimconnException
as e
:
2989 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2990 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2991 #update nets Change from VIM format to NFVO format
2994 net_nfvo
={'datacenter_id': datacenter_id
}
2995 net_nfvo
['name'] = net
['name']
2996 #net_nfvo['description']= net['name']
2997 net_nfvo
['vim_net_id'] = net
['id']
2998 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2999 net_nfvo
['shared'] = net
['shared']
3000 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3001 net_list
.append(net_nfvo
)
3002 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
3003 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
3005 elif 'net-edit' in action_dict
:
3006 net
= action_dict
['net-edit'].pop('net')
3007 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3008 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
3009 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3011 elif 'net-delete' in action_dict
:
3012 net
= action_dict
['net-deelte'].get('net')
3013 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3014 result
= mydb
.delete_row(FROM
='datacenter_nets',
3015 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3019 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
3022 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
3023 #get datacenter info
3024 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3026 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
3027 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
3028 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
3032 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
3033 #get datacenter info
3034 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3037 action_dict
= action_dict
["netmap"]
3038 if 'vim_id' in action_dict
:
3039 filter_dict
["id"] = action_dict
['vim_id']
3040 if 'vim_name' in action_dict
:
3041 filter_dict
["name"] = action_dict
['vim_name']
3043 filter_dict
["shared"] = True
3046 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
3047 except vimconn
.vimconnException
as e
:
3048 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
3049 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3050 if len(vim_nets
)>1 and action_dict
:
3051 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
3052 elif len(vim_nets
)==0: # and action_dict:
3053 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
3055 for net
in vim_nets
:
3056 net_nfvo
={'datacenter_id': datacenter_id
}
3057 if action_dict
and "name" in action_dict
:
3058 net_nfvo
['name'] = action_dict
['name']
3060 net_nfvo
['name'] = net
['name']
3061 #net_nfvo['description']= net['name']
3062 net_nfvo
['vim_net_id'] = net
['id']
3063 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3064 net_nfvo
['shared'] = net
['shared']
3065 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3067 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
3068 net_nfvo
["status"] = "OK"
3069 net_nfvo
["uuid"] = net_id
3070 except db_base_Exception
as e
:
3074 net_nfvo
["status"] = "FAIL: " + str(e
)
3075 net_list
.append(net_nfvo
)
3079 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
3080 #get datacenter info
3081 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3084 if utils
.check_valid_uuid(name
):
3085 filter_dict
["id"] = name
3087 filter_dict
["name"] = name
3089 if item
=="networks":
3090 #filter_dict['tenant_id'] = myvim['tenant_id']
3091 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
3092 elif item
=="tenants":
3093 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
3094 elif item
== "images":
3095 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
3097 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3098 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
3099 if name
and len(content
)==1:
3100 return {item
[:-1]: content
[0]}
3101 elif name
and len(content
)==0:
3102 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
3105 return {item
: content
}
3106 except vimconn
.vimconnException
as e
:
3107 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
3108 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
3111 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
3112 #get datacenter info
3113 if tenant_id
== "any":
3116 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3118 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
3119 logger
.debug("vim_action_delete vim response: " + str(content
))
3120 items
= content
.values()[0]
3121 if type(items
)==list and len(items
)==0:
3122 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
3123 elif type(items
)==list and len(items
)>1:
3124 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
3125 else: # it is a dict
3126 item_id
= items
["id"]
3127 item_name
= str(items
.get("name"))
3130 if item
=="networks":
3131 content
= myvim
.delete_network(item_id
)
3132 elif item
=="tenants":
3133 content
= myvim
.delete_tenant(item_id
)
3134 elif item
== "images":
3135 content
= myvim
.delete_image(item_id
)
3137 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3138 except vimconn
.vimconnException
as e
:
3139 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
3140 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
3142 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
3145 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
3146 #get datacenter info
3147 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
3148 if tenant_id
== "any":
3150 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3152 if item
=="networks":
3153 net
= descriptor
["network"]
3154 net_name
= net
.pop("name")
3155 net_type
= net
.pop("type", "bridge")
3156 net_public
= net
.pop("shared", False)
3157 net_ipprofile
= net
.pop("ip_profile", None)
3158 net_vlan
= net
.pop("vlan", None)
3159 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
3160 elif item
=="tenants":
3161 tenant
= descriptor
["tenant"]
3162 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
3164 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3165 except vimconn
.vimconnException
as e
:
3166 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
3168 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
3170 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
3171 data
= ovim
.new_of_controller(sdn_controller
)
3172 logger
.debug('New SDN controller created with uuid {}'.format(data
))
3175 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
3176 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
3177 msg
= 'SDN controller {} updated'.format(data
)
3181 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
3182 if controller_id
== None:
3183 data
= ovim
.get_of_controllers()
3185 data
= ovim
.show_of_controller(controller_id
)
3187 msg
= 'SDN controller list:\n {}'.format(data
)
3191 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
3192 select_
= ('uuid', 'config')
3193 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
3194 for datacenter
in datacenters
:
3195 if datacenter
['config']:
3196 config
= yaml
.load(datacenter
['config'])
3197 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
3198 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
3200 data
= ovim
.delete_of_controller(controller_id
)
3201 msg
= 'SDN controller {} deleted'.format(data
)
3205 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
3206 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
3207 if len(controller
) < 1:
3208 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
3211 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
3213 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
3215 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
3216 switch_dpid
= sdn_controller
["dpid"]
3219 for compute_node
in sdn_port_mapping
:
3220 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
3222 element
["compute_node"] = compute_node
["compute_node"]
3223 for port
in compute_node
["ports"]:
3224 element
["pci"] = port
.get("pci")
3225 element
["switch_port"] = port
.get("switch_port")
3226 element
["switch_mac"] = port
.get("switch_mac")
3227 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
3228 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
3229 " or 'switch_mac'", HTTP_Bad_Request
)
3230 maps
.append(dict(element
))
3232 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
3234 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
3235 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
3238 "sdn-controller": None,
3239 "datacenter-id": datacenter_id
,
3241 "ports_mapping": list()
3244 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
3245 if datacenter
['config']:
3246 config
= yaml
.load(datacenter
['config'])
3247 if 'sdn-controller' in config
:
3248 controller_id
= config
['sdn-controller']
3249 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
3250 result
["sdn-controller"] = controller_id
3251 result
["dpid"] = sdn_controller
["dpid"]
3253 if result
["sdn-controller"] == None or result
["dpid"] == None:
3254 raise NfvoException("Not all SDN controller information for datacenter {} could be found: {}".format(datacenter_id
, result
),
3255 HTTP_Internal_Server_Error
)
3260 ports_correspondence_dict
= dict()
3262 if result
["sdn-controller"] != link
["ofc_id"]:
3263 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
3264 if result
["dpid"] != link
["switch_dpid"]:
3265 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
3267 element
["pci"] = link
["pci"]
3268 if link
["switch_port"]:
3269 element
["switch_port"] = link
["switch_port"]
3270 if link
["switch_mac"]:
3271 element
["switch_mac"] = link
["switch_mac"]
3273 if not link
["compute_node"] in ports_correspondence_dict
:
3275 content
["compute_node"] = link
["compute_node"]
3276 content
["ports"] = list()
3277 ports_correspondence_dict
[link
["compute_node"]] = content
3279 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
3281 for key
in sorted(ports_correspondence_dict
):
3282 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
3286 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
3287 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})