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'
131 ovim
= ovim_module
.ovim(ovim_configuration
)
134 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'
135 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
136 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
137 'user','passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
139 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
141 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
142 'datacenter_id': vim
.get('datacenter_id')}
144 extra
.update(yaml
.load(vim
["config"]))
145 if vim
.get('dt_config'):
146 extra
.update(yaml
.load(vim
["dt_config"]))
147 if vim
["type"] not in vimconn_imported
:
150 module
= "vimconn_" + vim
["type"]
151 pkg
= __import__("osm_ro." + module
)
152 vim_conn
= getattr(pkg
, module
)
153 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
154 # vim_conn = imp.load_module(vim["type"], *module_info)
155 vimconn_imported
[vim
["type"]] = vim_conn
156 except (IOError, ImportError) as e
:
157 # if module_info and module_info[0]:
158 # file.close(module_info[0])
159 raise NfvoException("Unknown vim type '{}'. Cannot open file '{}.py'; {}: {}".format(
160 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
162 thread_id
= vim
['datacenter_tenant_id']
163 vim_persistent_info
[thread_id
] = {}
166 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
167 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
168 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
169 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
170 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
171 user
=vim
['user'], passwd
=vim
['passwd'],
172 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
174 except Exception as e
:
175 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
176 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['vim_tenant_id'], vim
['vim_tenant_name'], vim
['vim_tenant_id'])
177 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, vim
['datacenter_name'],
178 vim
['datacenter_tenant_id'], db
=db
, db_lock
=db_lock
, ovim
=ovim
)
180 vim_threads
["running"][thread_id
] = new_thread
181 except db_base_Exception
as e
:
182 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
186 global ovim
, global_config
189 for thread_id
,thread
in vim_threads
["running"].items():
190 thread
.insert_task(new_task("exit", None))
191 vim_threads
["deleting"][thread_id
] = thread
192 vim_threads
["running"] = {}
193 if global_config
and global_config
.get("console_thread"):
194 for thread
in global_config
["console_thread"]:
195 thread
.terminate
= True
198 return ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config
["version"],
199 global_config
["version_date"] ))
202 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
204 return result, content:
205 <0, error_text upon error
206 nb_records, flavor_list on success
209 WHERE_dict
['vnf_id'] = vnf_id
210 if nfvo_tenant
is not None:
211 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
213 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
214 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
215 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
216 #print "get_flavor_list result:", result
217 #print "get_flavor_list content:", content
219 for flavor
in flavors
:
220 flavorList
.append(flavor
['flavor_id'])
224 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
226 return result, content:
227 <0, error_text upon error
228 nb_records, flavor_list on success
231 WHERE_dict
['vnf_id'] = vnf_id
232 if nfvo_tenant
is not None:
233 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
235 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
236 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
239 imageList
.append(image
['image_id'])
243 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
244 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
245 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
246 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
247 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
248 raise exception upon error
251 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
252 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
253 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
254 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
255 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
256 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
257 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
258 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'
259 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
260 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
261 'user','passwd', 'dt.config as dt_config')
263 from_
= 'datacenters as d'
264 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
266 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
269 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
270 'datacenter_id': vim
.get('datacenter_id')}
272 extra
.update(yaml
.load(vim
["config"]))
273 if vim
.get('dt_config'):
274 extra
.update(yaml
.load(vim
["dt_config"]))
275 if vim
["type"] not in vimconn_imported
:
278 module
= "vimconn_" + vim
["type"]
279 pkg
= __import__("osm_ro." + module
)
280 vim_conn
= getattr(pkg
, module
)
281 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
282 # vim_conn = imp.load_module(vim["type"], *module_info)
283 vimconn_imported
[vim
["type"]] = vim_conn
284 except (IOError, ImportError) as e
:
285 # if module_info and module_info[0]:
286 # file.close(module_info[0])
287 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
288 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
291 if 'datacenter_tenant_id' in vim
:
292 thread_id
= vim
["datacenter_tenant_id"]
293 if thread_id
not in vim_persistent_info
:
294 vim_persistent_info
[thread_id
] = {}
295 persistent_info
= vim_persistent_info
[thread_id
]
299 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
300 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
301 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
302 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
303 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
304 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
305 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
306 config
=extra
, persistent_info
=persistent_info
308 except Exception as e
:
309 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
311 except db_base_Exception
as e
:
312 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
315 def rollback(mydb
, vims
, rollback_list
):
317 #delete things by reverse order
318 for i
in range(len(rollback_list
)-1, -1, -1):
319 item
= rollback_list
[i
]
320 if item
["where"]=="vim":
321 if item
["vim_id"] not in vims
:
323 vim
=vims
[ item
["vim_id"] ]
325 if item
["what"]=="image":
326 vim
.delete_image(item
["uuid"])
327 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
328 elif item
["what"]=="flavor":
329 vim
.delete_flavor(item
["uuid"])
330 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
331 elif item
["what"]=="network":
332 vim
.delete_network(item
["uuid"])
333 elif item
["what"]=="vm":
334 vim
.delete_vminstance(item
["uuid"])
335 except vimconn
.vimconnException
as e
:
336 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
337 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
338 except db_base_Exception
as e
:
339 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
343 if item
["what"]=="image":
344 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
345 elif item
["what"]=="flavor":
346 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
347 except db_base_Exception
as e
:
348 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
349 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
350 if len(undeleted_items
)==0:
351 return True," Rollback successful."
353 return False," Rollback fails to delete: " + str(undeleted_items
)
356 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
358 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
360 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
362 #dataplane interfaces
363 for numa
in vnfc
.get("numas",() ):
364 for interface
in numa
.get("interfaces",()):
365 if interface
["name"] in name_dict
:
367 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
368 vnfc
["name"], interface
["name"]),
370 name_dict
[ interface
["name"] ] = "underlay"
372 for interface
in vnfc
.get("bridge-ifaces",() ):
373 if interface
["name"] in name_dict
:
375 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
376 vnfc
["name"], interface
["name"]),
378 name_dict
[ interface
["name"] ] = "overlay"
379 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
380 # check bood-data info
381 if "boot-data" in vnfc
:
382 # check that user-data is incompatible with users and config-files
383 if (vnfc
["boot-data"].get("users") or vnfc
["boot-data"].get("config-files")) and vnfc
["boot-data"].get("user-data"):
385 "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
388 #check if the info in external_connections matches with the one in the vnfcs
390 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
391 if external_connection
["name"] in name_list
:
393 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
394 external_connection
["name"]),
396 name_list
.append(external_connection
["name"])
397 if external_connection
["VNFC"] not in vnfc_interfaces
:
399 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
400 external_connection
["name"], external_connection
["VNFC"]),
403 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
405 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
406 external_connection
["name"],
407 external_connection
["local_iface_name"]),
410 #check if the info in internal_connections matches with the one in the vnfcs
412 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
413 if internal_connection
["name"] in name_list
:
415 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
416 internal_connection
["name"]),
418 name_list
.append(internal_connection
["name"])
419 #We should check that internal-connections of type "ptp" have only 2 elements
421 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
423 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
424 internal_connection
["name"],
425 'ptp' if vnf_descriptor_version
==1 else 'e-line',
426 'data' if vnf_descriptor_version
==1 else "e-lan"),
428 for port
in internal_connection
["elements"]:
430 iface
= port
["local_iface_name"]
431 if vnf
not in vnfc_interfaces
:
433 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
434 internal_connection
["name"], vnf
),
436 if iface
not in vnfc_interfaces
[ vnf
]:
438 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
439 internal_connection
["name"], iface
),
441 return -HTTP_Bad_Request
,
442 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
443 if vnfc_interfaces
[vnf
][iface
] == "overlay":
444 internal_connection
["type"] = "bridge"
446 internal_connection
["type"] = "data"
447 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
448 if vnfc_interfaces
[vnf
][iface
] == "overlay":
449 internal_connection
["implementation"] = "overlay"
451 internal_connection
["implementation"] = "underlay"
452 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
453 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
455 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
456 internal_connection
["name"],
457 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
458 'data' if vnf_descriptor_version
==1 else 'underlay'),
460 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
461 vnfc_interfaces
[vnf
][iface
] == "underlay":
463 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
464 internal_connection
["name"], iface
,
465 'data' if vnf_descriptor_version
==1 else 'underlay',
466 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
470 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
472 if only_create_at_vim
:
473 image_mano_id
= image_dict
['uuid']
474 if return_on_error
== None:
475 return_on_error
= True
477 if image_dict
['location']:
478 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
480 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
482 image_mano_id
= images
[0]['uuid']
484 #create image in MANO DB
485 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
486 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
487 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
489 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
490 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
491 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
492 #create image at every vim
493 for vim_id
,vim
in vims
.iteritems():
494 image_created
="false"
496 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
497 #look at VIM if this image exist
499 if image_dict
['location'] is not None:
500 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
503 filter_dict
['name'] = image_dict
['universal_name']
504 if image_dict
.get('checksum') != None:
505 filter_dict
['checksum'] = image_dict
['checksum']
506 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
507 vim_images
= vim
.get_image_list(filter_dict
)
508 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
509 if len(vim_images
) > 1:
510 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), HTTP_Conflict
)
511 elif len(vim_images
) == 0:
512 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
514 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
515 image_vim_id
= vim_images
[0]['id']
517 except vimconn
.vimconnNotFoundException
as e
:
518 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
520 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
521 if image_dict
['location']:
522 image_vim_id
= vim
.new_image(image_dict
)
523 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
526 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
527 raise vimconn
.vimconnException(str(e
))
528 except vimconn
.vimconnException
as e
:
530 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
533 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
535 except vimconn
.vimconnException
as e
:
537 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
539 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
542 #if we reach here, the image has been created or existed
544 #add new vim_id at datacenters_images
545 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
546 elif image_db
[0]["vim_id"]!=image_vim_id
:
547 #modify existing vim_id at datacenters_images
548 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
550 return image_vim_id
if only_create_at_vim
else image_mano_id
553 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
554 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
555 'ram':flavor_dict
.get('ram'),
556 'vcpus':flavor_dict
.get('vcpus'),
558 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
559 del flavor_dict
['extended']
560 if 'extended' in flavor_dict
:
561 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
563 #look if flavor exist
564 if only_create_at_vim
:
565 flavor_mano_id
= flavor_dict
['uuid']
566 if return_on_error
== None:
567 return_on_error
= True
569 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
571 flavor_mano_id
= flavors
[0]['uuid']
574 #create one by one the images of aditional disks
575 dev_image_list
=[] #list of images
576 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
578 for device
in flavor_dict
['extended'].get('devices',[]):
579 if "image" not in device
and "image name" not in device
:
582 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
583 image_dict
['universal_name']=device
.get('image name')
584 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
585 image_dict
['location']=device
.get('image')
586 #image_dict['new_location']=vnfc.get('image location')
587 image_dict
['checksum']=device
.get('image checksum')
588 image_metadata_dict
= device
.get('image metadata', None)
589 image_metadata_str
= None
590 if image_metadata_dict
!= None:
591 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
592 image_dict
['metadata']=image_metadata_str
593 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
594 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
595 dev_image_list
.append(image_id
)
597 temp_flavor_dict
['name'] = flavor_dict
['name']
598 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
599 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
600 flavor_mano_id
= content
601 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
602 #create flavor at every vim
603 if 'uuid' in flavor_dict
:
604 del flavor_dict
['uuid']
606 for vim_id
,vim
in vims
.items():
607 flavor_created
="false"
609 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
610 #look at VIM if this flavor exist SKIPPED
611 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
613 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
617 #Create the flavor in VIM
618 #Translate images at devices from MANO id to VIM id
620 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
621 #make a copy of original devices
624 for device
in flavor_dict
["extended"].get("devices",[]):
627 devices_original
.append(dev
)
628 if 'image' in device
:
630 if 'image metadata' in device
:
631 del device
['image metadata']
633 for index
in range(0,len(devices_original
)) :
634 device
=devices_original
[index
]
635 if "image" not in device
and "image name" not in device
:
637 disk_list
.append({'size': device
.get('size', default_volume_size
)})
640 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
641 image_dict
['universal_name']=device
.get('image name')
642 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
643 image_dict
['location']=device
.get('image')
644 #image_dict['new_location']=device.get('image location')
645 image_dict
['checksum']=device
.get('image checksum')
646 image_metadata_dict
= device
.get('image metadata', None)
647 image_metadata_str
= None
648 if image_metadata_dict
!= None:
649 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
650 image_dict
['metadata']=image_metadata_str
651 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
652 image_dict
["uuid"]=image_mano_id
653 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
655 #save disk information (image must be based on and size
656 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
658 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
661 #check that this vim_id exist in VIM, if not create
662 flavor_vim_id
=flavor_db
[0]["vim_id"]
664 vim
.get_flavor(flavor_vim_id
)
665 continue #flavor exist
666 except vimconn
.vimconnException
:
668 #create flavor at vim
669 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
672 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
673 flavor_create
="false"
674 except vimconn
.vimconnException
as e
:
677 if not flavor_vim_id
:
678 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
679 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
680 flavor_created
="true"
681 except vimconn
.vimconnException
as e
:
683 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
685 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
688 #if reach here the flavor has been create or exist
689 if len(flavor_db
)==0:
690 #add new vim_id at datacenters_flavors
691 extended_devices_yaml
= None
692 if len(disk_list
) > 0:
693 extended_devices
= dict()
694 extended_devices
['disks'] = disk_list
695 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
696 mydb
.new_row('datacenters_flavors',
697 {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
,
698 'created':flavor_created
,'extended': extended_devices_yaml
})
699 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
700 #modify existing vim_id at datacenters_flavors
701 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
703 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
706 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
709 # Step 1. Check the VNF descriptor
710 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
711 # Step 2. Check tenant exist
713 if tenant_id
!= "any":
714 check_tenant(mydb
, tenant_id
)
715 if "tenant_id" in vnf_descriptor
["vnf"]:
716 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
717 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
720 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
721 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
722 if global_config
["auto_push_VNF_to_VIMs"]:
723 vims
= get_vim(mydb
, tenant_id
)
725 # Step 4. Review the descriptor and add missing fields
726 #print vnf_descriptor
727 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
728 vnf_name
= vnf_descriptor
['vnf']['name']
729 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
730 if "physical" in vnf_descriptor
['vnf']:
731 del vnf_descriptor
['vnf']['physical']
732 #print vnf_descriptor
734 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
735 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
736 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
738 #For each VNFC, we add it to the VNFCDict and we create a flavor.
739 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
740 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
742 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
743 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
745 VNFCitem
["name"] = vnfc
['name']
746 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
748 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
751 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
752 myflavorDict
["description"] = VNFCitem
["description"]
753 myflavorDict
["ram"] = vnfc
.get("ram", 0)
754 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
755 myflavorDict
["disk"] = vnfc
.get("disk", 1)
756 myflavorDict
["extended"] = {}
758 devices
= vnfc
.get("devices")
760 myflavorDict
["extended"]["devices"] = devices
763 # 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
764 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
766 # Previous code has been commented
767 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
768 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
769 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
770 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
772 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
774 # print "Error creating flavor: unknown processor model. Rollback successful."
775 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
777 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
778 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
780 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
781 myflavorDict
['extended']['numas'] = vnfc
['numas']
785 # Step 6.2 New flavors are created in the VIM
786 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
788 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
789 VNFCitem
["flavor_id"] = flavor_id
790 VNFCDict
[vnfc
['name']] = VNFCitem
792 logger
.debug("Creating new images in the VIM for each VNFC")
793 # Step 6.3 New images are created in the VIM
794 #For each VNFC, we must create the appropriate image.
795 #This "for" loop might be integrated with the previous one
796 #In case this integration is made, the VNFCDict might become a VNFClist.
797 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
798 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
800 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
801 image_dict
['universal_name']=vnfc
.get('image name')
802 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
803 image_dict
['location']=vnfc
.get('VNFC image')
804 #image_dict['new_location']=vnfc.get('image location')
805 image_dict
['checksum']=vnfc
.get('image checksum')
806 image_metadata_dict
= vnfc
.get('image metadata', None)
807 image_metadata_str
= None
808 if image_metadata_dict
is not None:
809 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
810 image_dict
['metadata']=image_metadata_str
811 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
812 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
813 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
814 VNFCDict
[vnfc
['name']]["image_id"] = image_id
815 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
816 if vnfc
.get("boot-data"):
817 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
820 # Step 7. Storing the VNF descriptor in the repository
821 if "descriptor" not in vnf_descriptor
["vnf"]:
822 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
824 # Step 8. Adding the VNF to the NFVO DB
825 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
827 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
828 _
, message
= rollback(mydb
, vims
, rollback_list
)
829 if isinstance(e
, db_base_Exception
):
830 error_text
= "Exception at database"
831 elif isinstance(e
, KeyError):
832 error_text
= "KeyError exception "
833 e
.http_code
= HTTP_Internal_Server_Error
835 error_text
= "Exception at VIM"
836 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
837 #logger.error("start_scenario %s", error_text)
838 raise NfvoException(error_text
, e
.http_code
)
841 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
844 # Step 1. Check the VNF descriptor
845 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
846 # Step 2. Check tenant exist
848 if tenant_id
!= "any":
849 check_tenant(mydb
, tenant_id
)
850 if "tenant_id" in vnf_descriptor
["vnf"]:
851 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
852 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
855 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
856 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
857 if global_config
["auto_push_VNF_to_VIMs"]:
858 vims
= get_vim(mydb
, tenant_id
)
860 # Step 4. Review the descriptor and add missing fields
861 #print vnf_descriptor
862 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
863 vnf_name
= vnf_descriptor
['vnf']['name']
864 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
865 if "physical" in vnf_descriptor
['vnf']:
866 del vnf_descriptor
['vnf']['physical']
867 #print vnf_descriptor
869 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
870 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
871 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
873 #For each VNFC, we add it to the VNFCDict and we create a flavor.
874 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
875 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
877 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
878 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
880 VNFCitem
["name"] = vnfc
['name']
881 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
883 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
886 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
887 myflavorDict
["description"] = VNFCitem
["description"]
888 myflavorDict
["ram"] = vnfc
.get("ram", 0)
889 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
890 myflavorDict
["disk"] = vnfc
.get("disk", 1)
891 myflavorDict
["extended"] = {}
893 devices
= vnfc
.get("devices")
895 myflavorDict
["extended"]["devices"] = devices
898 # 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
899 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
901 # Previous code has been commented
902 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
903 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
904 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
905 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
907 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
909 # print "Error creating flavor: unknown processor model. Rollback successful."
910 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
912 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
913 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
915 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
916 myflavorDict
['extended']['numas'] = vnfc
['numas']
920 # Step 6.2 New flavors are created in the VIM
921 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
923 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
924 VNFCitem
["flavor_id"] = flavor_id
925 VNFCDict
[vnfc
['name']] = VNFCitem
927 logger
.debug("Creating new images in the VIM for each VNFC")
928 # Step 6.3 New images are created in the VIM
929 #For each VNFC, we must create the appropriate image.
930 #This "for" loop might be integrated with the previous one
931 #In case this integration is made, the VNFCDict might become a VNFClist.
932 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
933 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
935 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
936 image_dict
['universal_name']=vnfc
.get('image name')
937 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
938 image_dict
['location']=vnfc
.get('VNFC image')
939 #image_dict['new_location']=vnfc.get('image location')
940 image_dict
['checksum']=vnfc
.get('image checksum')
941 image_metadata_dict
= vnfc
.get('image metadata', None)
942 image_metadata_str
= None
943 if image_metadata_dict
is not None:
944 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
945 image_dict
['metadata']=image_metadata_str
946 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
947 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
948 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
949 VNFCDict
[vnfc
['name']]["image_id"] = image_id
950 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
951 if vnfc
.get("boot-data"):
952 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
954 # Step 7. Storing the VNF descriptor in the repository
955 if "descriptor" not in vnf_descriptor
["vnf"]:
956 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
958 # Step 8. Adding the VNF to the NFVO DB
959 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
961 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
962 _
, message
= rollback(mydb
, vims
, rollback_list
)
963 if isinstance(e
, db_base_Exception
):
964 error_text
= "Exception at database"
965 elif isinstance(e
, KeyError):
966 error_text
= "KeyError exception "
967 e
.http_code
= HTTP_Internal_Server_Error
969 error_text
= "Exception at VIM"
970 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
971 #logger.error("start_scenario %s", error_text)
972 raise NfvoException(error_text
, e
.http_code
)
975 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
976 #check valid tenant_id
977 check_tenant(mydb
, tenant_id
)
980 if tenant_id
!= "any":
981 where_or
["tenant_id"] = tenant_id
982 where_or
["public"] = True
983 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
986 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
987 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
988 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
989 data
={'vnf' : filtered_content
}
991 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
992 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description', 'boot_data'),
993 WHERE
={'vnfs.uuid': vnf_id
} )
995 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
996 # change boot_data into boot-data
998 if vm
.get("boot_data"):
999 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1002 data
['vnf']['VNFC'] = content
1003 #TODO: GET all the information from a VNFC and include it in the output.
1006 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1007 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1008 WHERE
={'vnfs.uuid': vnf_id
} )
1009 data
['vnf']['nets'] = content
1011 #GET ip-profile for each net
1012 for net
in data
['vnf']['nets']:
1013 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1014 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1015 WHERE
={'net_id': net
["uuid"]} )
1016 if len(ipprofiles
)==1:
1017 net
["ip_profile"] = ipprofiles
[0]
1018 elif len(ipprofiles
)>1:
1019 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
1022 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1024 #GET External Interfaces
1025 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1026 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1027 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1028 WHERE
={'vnfs.uuid': vnf_id
},
1029 WHERE_NOT
={'interfaces.external_name': None} )
1031 data
['vnf']['external-connections'] = content
1036 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1037 # Check tenant exist
1038 if tenant_id
!= "any":
1039 check_tenant(mydb
, tenant_id
)
1040 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1041 vims
= get_vim(mydb
, tenant_id
)
1045 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1047 if tenant_id
!= "any":
1048 where_or
["tenant_id"] = tenant_id
1049 where_or
["public"] = True
1050 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1051 vnf_id
= vnf
["uuid"]
1053 # "Getting the list of flavors and tenants of the VNF"
1054 flavorList
= get_flavorlist(mydb
, vnf_id
)
1055 if len(flavorList
)==0:
1056 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1058 imageList
= get_imagelist(mydb
, vnf_id
)
1059 if len(imageList
)==0:
1060 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1062 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1064 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1067 for flavor
in flavorList
:
1068 #check if flavor is used by other vnf
1070 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1072 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1074 #flavor not used, must be deleted
1076 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
1077 for flavor_vim
in c
:
1078 if flavor_vim
["datacenter_id"] not in vims
:
1080 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
1082 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
1084 myvim
.delete_flavor(flavor_vim
["vim_id"])
1085 except vimconn
.vimconnNotFoundException
as e
:
1086 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
1087 except vimconn
.vimconnException
as e
:
1088 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1089 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1090 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
1091 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1092 mydb
.delete_row_by_id('flavors', flavor
)
1093 except db_base_Exception
as e
:
1094 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1095 undeletedItems
.append("flavor %s" % flavor
)
1098 for image
in imageList
:
1100 #check if image is used by other vnf
1101 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1103 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1105 #image not used, must be deleted
1107 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1109 if image_vim
["datacenter_id"] not in vims
:
1111 if image_vim
['created']=='false': #skip this image because not created by openmano
1113 myvim
=vims
[ image_vim
["datacenter_id"] ]
1115 myvim
.delete_image(image_vim
["vim_id"])
1116 except vimconn
.vimconnNotFoundException
as e
:
1117 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1118 except vimconn
.vimconnException
as e
:
1119 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1120 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1121 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1122 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1123 mydb
.delete_row_by_id('images', image
)
1124 except db_base_Exception
as e
:
1125 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1126 undeletedItems
.append("image %s" % image
)
1128 return vnf_id
+ " " + vnf
["name"]
1130 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1133 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1134 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1138 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1139 myvim
= vims
.values()[0]
1140 result
,servers
= myvim
.get_hosts_info()
1142 return result
, servers
1143 topology
= {'name':myvim
['name'] , 'servers': servers
}
1144 return result
, topology
1147 def get_hosts(mydb
, nfvo_tenant_id
):
1148 vims
= get_vim(mydb
, nfvo_tenant_id
)
1150 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1152 #print "nfvo.datacenter_action() error. Several datacenters found"
1153 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1154 myvim
= vims
.values()[0]
1156 hosts
= myvim
.get_hosts()
1157 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1159 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1161 server
={'name':host
['name'], 'vms':[]}
1162 for vm
in host
['instances']:
1163 #get internal name and model
1165 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1166 WHERE
={'vim_vm_id':vm
['id']} )
1168 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1170 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1172 except db_base_Exception
as e
:
1173 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1174 datacenter
['Datacenters'][0]['servers'].append(server
)
1175 #return -400, "en construccion"
1177 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1179 except vimconn
.vimconnException
as e
:
1180 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1183 def new_scenario(mydb
, tenant_id
, topo
):
1185 # result, vims = get_vim(mydb, tenant_id)
1187 # return result, vims
1189 if tenant_id
!= "any":
1190 check_tenant(mydb
, tenant_id
)
1191 if "tenant_id" in topo
:
1192 if topo
["tenant_id"] != tenant_id
:
1193 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1198 #1.1: get VNFs and external_networks (other_nets).
1200 other_nets
={} #external_networks, bridge_networks and data_networkds
1201 nodes
= topo
['topology']['nodes']
1202 for k
in nodes
.keys():
1203 if nodes
[k
]['type'] == 'VNF':
1205 vnfs
[k
]['ifaces'] = {}
1206 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1207 other_nets
[k
] = nodes
[k
]
1208 other_nets
[k
]['external']=True
1209 elif nodes
[k
]['type'] == 'network':
1210 other_nets
[k
] = nodes
[k
]
1211 other_nets
[k
]['external']=False
1214 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1215 for name
,vnf
in vnfs
.items():
1217 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1219 error_pos
= "'topology':'nodes':'" + name
+ "'"
1221 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1222 where
['uuid'] = vnf
['vnf_id']
1223 if 'VNF model' in vnf
:
1224 error_text
+= " 'VNF model' " + vnf
['VNF model']
1225 where
['name'] = vnf
['VNF model']
1227 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1229 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1235 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1237 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1238 vnf
['uuid']=vnf_db
[0]['uuid']
1239 vnf
['description']=vnf_db
[0]['description']
1240 #get external interfaces
1241 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1242 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1243 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1244 for ext_iface
in ext_ifaces
:
1245 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1247 #1.4 get list of connections
1248 conections
= topo
['topology']['connections']
1249 conections_list
= []
1250 conections_list_name
= []
1251 for k
in conections
.keys():
1252 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1253 ifaces_list
= conections
[k
]['nodes'].items()
1254 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1256 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1257 for k2
in conection_pair_list
:
1260 con_type
= conections
[k
].get("type", "link")
1261 if con_type
!= "link":
1263 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1264 other_nets
[k
] = {'external': False}
1265 if conections
[k
].get("graph"):
1266 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1267 ifaces_list
.append( (k
, None) )
1270 if con_type
== "external_network":
1271 other_nets
[k
]['external'] = True
1272 if conections
[k
].get("model"):
1273 other_nets
[k
]["model"] = conections
[k
]["model"]
1275 other_nets
[k
]["model"] = k
1276 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1277 other_nets
[k
]["model"] = con_type
1279 conections_list_name
.append(k
)
1280 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)
1281 #print set(ifaces_list)
1282 #check valid VNF and iface names
1283 for iface
in ifaces_list
:
1284 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1285 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1286 str(k
), iface
[0]), HTTP_Not_Found
)
1287 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1288 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1289 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1291 #1.5 unify connections from the pair list to a consolidated list
1293 while index
< len(conections_list
):
1295 while index2
< len(conections_list
):
1296 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1297 conections_list
[index
] |
= conections_list
[index2
]
1298 del conections_list
[index2
]
1299 del conections_list_name
[index2
]
1302 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1304 #for k in conections_list:
1309 #1.6 Delete non external nets
1310 # for k in other_nets.keys():
1311 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1312 # for con in conections_list:
1314 # for index in range(0,len(con)):
1315 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1316 # for index in delete_indexes:
1319 #1.7: Check external_ports are present at database table datacenter_nets
1320 for k
,net
in other_nets
.items():
1321 error_pos
= "'topology':'nodes':'" + k
+ "'"
1322 if net
['external']==False:
1323 if 'name' not in net
:
1325 if 'model' not in net
:
1326 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1327 if net
['model']=='bridge_net':
1328 net
['type']='bridge';
1329 elif net
['model']=='dataplane_net':
1332 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1334 #IF we do not want to check that external network exist at datacenter
1339 # if 'net_id' in net:
1340 # error_text += " 'net_id' " + net['net_id']
1341 # WHERE_['uuid'] = net['net_id']
1342 # if 'model' in net:
1343 # error_text += " 'model' " + net['model']
1344 # WHERE_['name'] = net['model']
1345 # if len(WHERE_) == 0:
1346 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1347 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1348 # FROM='datacenter_nets', WHERE=WHERE_ )
1350 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1352 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1353 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1355 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1356 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1357 # other_nets[k].update(net_db[0])
1360 net_nb
=0 #Number of nets
1361 for con
in conections_list
:
1362 #check if this is connected to a external net
1366 for index
in range(0,len(con
)):
1367 #check if this is connected to a external net
1368 for net_key
in other_nets
.keys():
1369 if con
[index
][0]==net_key
:
1370 if other_net_index
>=0:
1371 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1372 #print "nfvo.new_scenario " + error_text
1373 raise NfvoException(error_text
, HTTP_Bad_Request
)
1375 other_net_index
= index
1376 net_target
= net_key
1378 #print "other_net_index", other_net_index
1380 if other_net_index
>=0:
1381 del con
[other_net_index
]
1382 #IF we do not want to check that external network exist at datacenter
1383 if other_nets
[net_target
]['external'] :
1384 if "name" not in other_nets
[net_target
]:
1385 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1386 if other_nets
[net_target
]["type"] == "external_network":
1387 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1388 other_nets
[net_target
]["type"] = "data"
1390 other_nets
[net_target
]["type"] = "bridge"
1392 # if other_nets[net_target]['external'] :
1393 # 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
1394 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1395 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1396 # print "nfvo.new_scenario " + error_text
1397 # return -HTTP_Bad_Request, error_text
1400 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1403 net_type_bridge
=False
1405 net_target
= "__-__net"+str(net_nb
)
1406 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1407 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1410 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1411 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1412 if iface_type
=='mgmt' or iface_type
=='bridge':
1413 net_type_bridge
= True
1415 net_type_data
= True
1416 if net_type_bridge
and net_type_data
:
1417 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1418 #print "nfvo.new_scenario " + error_text
1419 raise NfvoException(error_text
, HTTP_Bad_Request
)
1420 elif net_type_bridge
:
1423 type_
='data' if len(con
)>2 else 'ptp'
1424 net_list
[net_target
]['type'] = type_
1427 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1428 #print "nfvo.new_scenario " + error_text
1430 raise NfvoException(error_text
, HTTP_Bad_Request
)
1432 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1433 #1.8.1 obtain management net
1434 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1435 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1436 #1.8.2 check all interfaces from all vnfs
1438 add_mgmt_net
= False
1439 for vnf
in vnfs
.values():
1440 for iface
in vnf
['ifaces'].values():
1441 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1442 #iface not connected
1443 iface
['net_key'] = 'mgmt'
1445 if add_mgmt_net
and 'mgmt' not in net_list
:
1446 net_list
['mgmt']=mgmt_net
[0]
1447 net_list
['mgmt']['external']=True
1448 net_list
['mgmt']['graph']={'visible':False}
1450 net_list
.update(other_nets
)
1452 #print 'net_list', net_list
1457 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1458 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1459 'tenant_id':tenant_id
, 'name':topo
['name'],
1460 'description':topo
.get('description',topo
['name']),
1461 'public': topo
.get('public', False)
1467 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
1468 """ This creates a new scenario for version 0.2 and 0.3"""
1469 scenario
= scenario_dict
["scenario"]
1470 if tenant_id
!= "any":
1471 check_tenant(mydb
, tenant_id
)
1472 if "tenant_id" in scenario
:
1473 if scenario
["tenant_id"] != tenant_id
:
1474 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1475 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1476 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1480 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
1481 for name
,vnf
in scenario
["vnfs"].iteritems():
1483 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1485 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1487 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1488 where
['uuid'] = vnf
['vnf_id']
1489 if 'vnf_name' in vnf
:
1490 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1491 where
['name'] = vnf
['vnf_name']
1493 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1494 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
1499 if len(vnf_db
) == 0:
1500 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1501 elif len(vnf_db
) > 1:
1502 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1503 vnf
['uuid'] = vnf_db
[0]['uuid']
1504 vnf
['description'] = vnf_db
[0]['description']
1506 # get external interfaces
1507 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
1508 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1509 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name': None} )
1510 for ext_iface
in ext_ifaces
:
1511 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
1512 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1514 # 2: Insert net_key and ip_address at every vnf interface
1515 for net_name
, net
in scenario
["networks"].items():
1516 net_type_bridge
= False
1517 net_type_data
= False
1518 for iface_dict
in net
["interfaces"]:
1519 if version
== "0.2":
1520 temp_dict
= iface_dict
1522 elif version
== "0.3":
1523 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
1524 ip_address
= iface_dict
.get('ip_address', None)
1525 for vnf
, iface
in temp_dict
.items():
1526 if vnf
not in scenario
["vnfs"]:
1527 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
1529 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1530 raise NfvoException(error_text
, HTTP_Not_Found
)
1531 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1532 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
1533 .format(net_name
, iface
)
1534 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1535 raise NfvoException(error_text
, HTTP_Bad_Request
)
1536 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1537 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
1538 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1539 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1540 raise NfvoException(error_text
, HTTP_Bad_Request
)
1541 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1542 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
1543 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1544 if iface_type
== 'mgmt' or iface_type
== 'bridge':
1545 net_type_bridge
= True
1547 net_type_data
= True
1549 if net_type_bridge
and net_type_data
:
1550 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
1552 # logger.debug("nfvo.new_scenario " + error_text)
1553 raise NfvoException(error_text
, HTTP_Bad_Request
)
1554 elif net_type_bridge
:
1557 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
1559 if net
.get("implementation"): # for v0.3
1560 if type_
== "bridge" and net
["implementation"] == "underlay":
1561 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
1562 "'network':'{}'".format(net_name
)
1563 # logger.debug(error_text)
1564 raise NfvoException(error_text
, HTTP_Bad_Request
)
1565 elif type_
!= "bridge" and net
["implementation"] == "overlay":
1566 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
1567 "'network':'{}'".format(net_name
)
1568 # logger.debug(error_text)
1569 raise NfvoException(error_text
, HTTP_Bad_Request
)
1570 net
.pop("implementation")
1571 if "type" in net
and version
== "0.3": # for v0.3
1572 if type_
== "data" and net
["type"] == "e-line":
1573 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
1574 "'e-line' at 'network':'{}'".format(net_name
)
1575 # logger.debug(error_text)
1576 raise NfvoException(error_text
, HTTP_Bad_Request
)
1577 elif type_
== "ptp" and net
["type"] == "e-lan":
1581 net
['name'] = net_name
1582 net
['external'] = net
.get('external', False)
1584 # 3: insert at database
1585 scenario
["nets"] = scenario
["networks"]
1586 scenario
['tenant_id'] = tenant_id
1587 scenario_id
= mydb
.new_scenario(scenario
)
1591 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1592 data
["uuid"] = scenario_id
1593 data
["tenant_id"] = tenant_id
1594 c
= mydb
.edit_scenario( data
)
1598 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1599 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1600 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
1601 vims
= {datacenter_id
: myvim
}
1602 myvim_tenant
= myvim
['tenant_id']
1603 datacenter_name
= myvim
['name']
1607 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1608 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1609 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
1610 scenarioDict
['datacenter_id'] = datacenter_id
1611 #print '================scenarioDict======================='
1612 #print json.dumps(scenarioDict, indent=4)
1613 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1615 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1616 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1618 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1619 auxNetDict
['scenario'] = {}
1621 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1622 for sce_net
in scenarioDict
['nets']:
1623 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1625 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1626 myNetName
= myNetName
[0:255] #limit length
1627 myNetType
= sce_net
['type']
1629 myNetDict
["name"] = myNetName
1630 myNetDict
["type"] = myNetType
1631 myNetDict
["tenant_id"] = myvim_tenant
1632 myNetIPProfile
= sce_net
.get('ip_profile', None)
1634 #We should use the dictionary as input parameter for new_network
1636 if not sce_net
["external"]:
1637 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1638 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1639 sce_net
['vim_id'] = network_id
1640 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1641 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1642 sce_net
["created"] = True
1644 if sce_net
['vim_id'] == None:
1645 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1646 _
, message
= rollback(mydb
, vims
, rollbackList
)
1647 logger
.error("nfvo.start_scenario: %s", error_text
)
1648 raise NfvoException(error_text
, HTTP_Bad_Request
)
1649 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1650 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1652 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1653 #For each vnf net, we create it and we add it to instanceNetlist.
1654 for sce_vnf
in scenarioDict
['vnfs']:
1655 for net
in sce_vnf
['nets']:
1656 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1658 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1659 myNetName
= myNetName
[0:255] #limit length
1660 myNetType
= net
['type']
1662 myNetDict
["name"] = myNetName
1663 myNetDict
["type"] = myNetType
1664 myNetDict
["tenant_id"] = myvim_tenant
1665 myNetIPProfile
= net
.get('ip_profile', None)
1668 #We should use the dictionary as input parameter for new_network
1669 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1670 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1671 net
['vim_id'] = network_id
1672 if sce_vnf
['uuid'] not in auxNetDict
:
1673 auxNetDict
[sce_vnf
['uuid']] = {}
1674 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1675 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1676 net
["created"] = True
1678 #print "auxNetDict:"
1679 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1681 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1682 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1684 for sce_vnf
in scenarioDict
['vnfs']:
1685 for vm
in sce_vnf
['vms']:
1688 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1689 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
1690 #myVMDict['description'] = vm['description']
1691 myVMDict
['description'] = myVMDict
['name'][0:99]
1693 myVMDict
['start'] = "no"
1694 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1695 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1697 #create image at vim in case it not exist
1698 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1699 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1700 vm
['vim_image_id'] = image_id
1702 #create flavor at vim in case it not exist
1703 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1704 if flavor_dict
['extended']!=None:
1705 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1706 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1707 vm
['vim_flavor_id'] = flavor_id
1710 myVMDict
['imageRef'] = vm
['vim_image_id']
1711 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1712 myVMDict
['networks'] = []
1713 for iface
in vm
['interfaces']:
1715 if iface
['type']=="data":
1716 netDict
['type'] = iface
['model']
1717 elif "model" in iface
and iface
["model"]!=None:
1718 netDict
['model']=iface
['model']
1719 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1720 #discover type of interface looking at flavor
1721 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1722 for flavor_iface
in numa
.get('interfaces',[]):
1723 if flavor_iface
.get('name') == iface
['internal_name']:
1724 if flavor_iface
['dedicated'] == 'yes':
1725 netDict
['type']="PF" #passthrough
1726 elif flavor_iface
['dedicated'] == 'no':
1727 netDict
['type']="VF" #siov
1728 elif flavor_iface
['dedicated'] == 'yes:sriov':
1729 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1730 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1732 netDict
["use"]=iface
['type']
1733 if netDict
["use"]=="data" and not netDict
.get("type"):
1734 #print "netDict", netDict
1735 #print "iface", iface
1736 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'])
1737 if flavor_dict
.get('extended')==None:
1738 raise NfvoException(e_text
+ "After database migration some information is not available. \
1739 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1741 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1742 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1743 netDict
["type"]="virtual"
1744 if "vpci" in iface
and iface
["vpci"] is not None:
1745 netDict
['vpci'] = iface
['vpci']
1746 if "mac" in iface
and iface
["mac"] is not None:
1747 netDict
['mac_address'] = iface
['mac']
1748 if "port-security" in iface
and iface
["port-security"] is not None:
1749 netDict
['port_security'] = iface
['port-security']
1750 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
1751 netDict
['floating_ip'] = iface
['floating-ip']
1752 netDict
['name'] = iface
['internal_name']
1753 if iface
['net_id'] is None:
1754 for vnf_iface
in sce_vnf
["interfaces"]:
1757 if vnf_iface
['interface_id']==iface
['uuid']:
1758 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1761 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1762 #skip bridge ifaces not connected to any net
1763 #if 'net_id' not in netDict or netDict['net_id']==None:
1765 myVMDict
['networks'].append(netDict
)
1766 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1767 #print myVMDict['name']
1768 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1769 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1770 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1771 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1772 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1773 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1774 vm
['vim_id'] = vm_id
1775 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1776 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1777 for net
in myVMDict
['networks']:
1779 for iface
in vm
['interfaces']:
1780 if net
["name"]==iface
["internal_name"]:
1781 iface
["vim_id"]=net
["vim_id"]
1784 logger
.debug("start scenario Deployment done")
1785 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1786 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1787 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1788 return mydb
.get_instance_scenario(instance_id
)
1790 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1791 _
, message
= rollback(mydb
, vims
, rollbackList
)
1792 if isinstance(e
, db_base_Exception
):
1793 error_text
= "Exception at database"
1795 error_text
= "Exception at VIM"
1796 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1797 #logger.error("start_scenario %s", error_text)
1798 raise NfvoException(error_text
, e
.http_code
)
1801 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
1802 ''' join the cloud config information into cloud_config_preserve.
1803 In case of conflict cloud_config_preserve preserves
1806 if not cloud_config_preserve
and not cloud_config
:
1809 new_cloud_config
= {"key-pairs":[], "users":[]}
1811 if cloud_config_preserve
:
1812 for key
in cloud_config_preserve
.get("key-pairs", () ):
1813 if key
not in new_cloud_config
["key-pairs"]:
1814 new_cloud_config
["key-pairs"].append(key
)
1816 for key
in cloud_config
.get("key-pairs", () ):
1817 if key
not in new_cloud_config
["key-pairs"]:
1818 new_cloud_config
["key-pairs"].append(key
)
1819 if not new_cloud_config
["key-pairs"]:
1820 del new_cloud_config
["key-pairs"]
1824 new_cloud_config
["users"] += cloud_config
.get("users", () )
1825 if cloud_config_preserve
:
1826 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
1827 index_to_delete
= []
1828 users
= new_cloud_config
.get("users", [])
1829 for index0
in range(0,len(users
)):
1830 if index0
in index_to_delete
:
1832 for index1
in range(index0
+1,len(users
)):
1833 if index1
in index_to_delete
:
1835 if users
[index0
]["name"] == users
[index1
]["name"]:
1836 index_to_delete
.append(index1
)
1837 for key
in users
[index1
].get("key-pairs",()):
1838 if "key-pairs" not in users
[index0
]:
1839 users
[index0
]["key-pairs"] = [key
]
1840 elif key
not in users
[index0
]["key-pairs"]:
1841 users
[index0
]["key-pairs"].append(key
)
1842 index_to_delete
.sort(reverse
=True)
1843 for index
in index_to_delete
:
1845 if not new_cloud_config
["users"]:
1846 del new_cloud_config
["users"]
1849 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
1850 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
1851 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
1852 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
1855 if cloud_config
and cloud_config
.get("user-data") != None:
1856 new_cloud_config
["user-data"] = cloud_config
["user-data"]
1857 if cloud_config_preserve
and cloud_config_preserve
.get("user-data") != None:
1858 new_cloud_config
["user-data"] = cloud_config_preserve
["user-data"]
1861 new_cloud_config
["config-files"] = []
1862 if cloud_config
and cloud_config
.get("config-files") != None:
1863 new_cloud_config
["config-files"] += cloud_config
["config-files"]
1864 if cloud_config_preserve
:
1865 for file in cloud_config_preserve
.get("config-files", ()):
1866 for index
in range(0, len(new_cloud_config
["config-files"])):
1867 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
1868 new_cloud_config
["config-files"][index
] = file
1871 new_cloud_config
["config-files"].append(file)
1872 if not new_cloud_config
["config-files"]:
1873 del new_cloud_config
["config-files"]
1874 return new_cloud_config
1877 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
1878 datacenter_id
= None
1879 datacenter_name
= None
1882 if datacenter_tenant_id
:
1883 thread_id
= datacenter_tenant_id
1884 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
1886 where_
={"td.nfvo_tenant_id": tenant_id
}
1887 if datacenter_id_name
:
1888 if utils
.check_valid_uuid(datacenter_id_name
):
1889 datacenter_id
= datacenter_id_name
1890 where_
["dt.datacenter_id"] = datacenter_id
1892 datacenter_name
= datacenter_id_name
1893 where_
["d.name"] = datacenter_name
1894 if datacenter_tenant_id
:
1895 where_
["dt.uuid"] = datacenter_tenant_id
1896 datacenters
= mydb
.get_rows(
1897 SELECT
=("dt.uuid as datacenter_tenant_id",),
1898 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
1899 "join datacenters as d on d.uuid=dt.datacenter_id",
1901 if len(datacenters
) > 1:
1902 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1904 thread_id
= datacenters
[0]["datacenter_tenant_id"]
1905 thread
= vim_threads
["running"].get(thread_id
)
1907 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1908 return thread_id
, thread
1909 except db_base_Exception
as e
:
1910 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
1912 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1913 datacenter_id
= None
1914 datacenter_name
= None
1915 if datacenter_id_name
:
1916 if utils
.check_valid_uuid(datacenter_id_name
):
1917 datacenter_id
= datacenter_id_name
1919 datacenter_name
= datacenter_id_name
1920 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1922 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1924 #print "nfvo.datacenter_action() error. Several datacenters found"
1925 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1926 return vims
.keys()[0], vims
.values()[0]
1930 '''Takes dict d and updates it with the values in dict u.'''
1931 '''It merges all depth levels'''
1932 for k
, v
in u
.iteritems():
1933 if isinstance(v
, collections
.Mapping
):
1934 r
= update(d
.get(k
, {}), v
)
1941 def create_instance(mydb
, tenant_id
, instance_dict
):
1942 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1943 # logger.debug("Creating instance...")
1944 scenario
= instance_dict
["scenario"]
1946 #find main datacenter
1948 myvim_threads_id
= {}
1951 datacenter
= instance_dict
.get("datacenter")
1952 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1953 myvims
[default_datacenter_id
] = vim
1954 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
1955 tasks_to_launch
[myvim_threads_id
[default_datacenter_id
]] = []
1956 #myvim_tenant = myvim['tenant_id']
1957 # default_datacenter_name = vim['name']
1960 #print "Checking that the scenario exists and getting the scenario dictionary"
1961 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1963 #logger.debug(">>>>>>> Dictionaries before merging")
1964 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1965 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1967 scenarioDict
['datacenter_id'] = default_datacenter_id
1969 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1970 auxNetDict
['scenario'] = {}
1972 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1973 instance_name
= instance_dict
["name"]
1974 instance_description
= instance_dict
.get("description")
1976 # 0 check correct parameters
1977 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1979 for scenario_net
in scenarioDict
['nets']:
1980 if net_name
== scenario_net
["name"]:
1984 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1985 if "sites" not in net_instance_desc
:
1986 net_instance_desc
["sites"] = [ {} ]
1987 site_without_datacenter_field
= False
1988 for site
in net_instance_desc
["sites"]:
1989 if site
.get("datacenter"):
1990 if site
["datacenter"] not in myvims
:
1991 #Add this datacenter to myvims
1992 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1994 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
1995 tasks_to_launch
[myvim_threads_id
[d
]] = []
1996 site
["datacenter"] = d
#change name to id
1998 if site_without_datacenter_field
:
1999 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
2000 site_without_datacenter_field
= True
2001 site
["datacenter"] = default_datacenter_id
#change name to id
2003 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
2005 for scenario_vnf
in scenarioDict
['vnfs']:
2006 if vnf_name
== scenario_vnf
['name']:
2010 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
2011 if "datacenter" in vnf_instance_desc
:
2012 # Add this datacenter to myvims
2013 if vnf_instance_desc
["datacenter"] not in myvims
:
2014 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2016 myvim_threads_id
[d
],_
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2017 tasks_to_launch
[myvim_threads_id
[d
]] = []
2018 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2020 #0.1 parse cloud-config parameters
2021 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2023 #0.2 merge instance information into scenario
2024 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2025 #However, this is not possible yet.
2026 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2027 for scenario_net
in scenarioDict
['nets']:
2028 if net_name
== scenario_net
["name"]:
2029 if 'ip-profile' in net_instance_desc
:
2030 ipprofile
= net_instance_desc
['ip-profile']
2031 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
2032 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
2033 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
2034 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
2035 if 'dhcp' in ipprofile
:
2036 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
2037 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
2038 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
2039 del ipprofile
['dhcp']
2040 if 'ip_profile' not in scenario_net
:
2041 scenario_net
['ip_profile'] = ipprofile
2043 update(scenario_net
['ip_profile'],ipprofile
)
2044 for interface
in net_instance_desc
.get('interfaces', () ):
2045 if 'ip_address' in interface
:
2046 for vnf
in scenarioDict
['vnfs']:
2047 if interface
['vnf'] == vnf
['name']:
2048 for vnf_interface
in vnf
['interfaces']:
2049 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2050 vnf_interface
['ip_address']=interface
['ip_address']
2052 #logger.debug(">>>>>>>> Merged dictionary")
2053 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
2056 # 1. Creating new nets (sce_nets) in the VIM"
2057 for sce_net
in scenarioDict
['nets']:
2058 sce_net
["vim_id_sites"]={}
2059 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
2060 net_name
= descriptor_net
.get("vim-network-name")
2061 auxNetDict
['scenario'][sce_net
['uuid']] = {}
2063 sites
= descriptor_net
.get("sites", [ {} ])
2065 if site
.get("datacenter"):
2066 vim
= myvims
[ site
["datacenter"] ]
2067 datacenter_id
= site
["datacenter"]
2068 myvim_thread_id
= myvim_threads_id
[ site
["datacenter"] ]
2070 vim
= myvims
[ default_datacenter_id
]
2071 datacenter_id
= default_datacenter_id
2072 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2073 net_type
= sce_net
['type']
2074 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
2075 if sce_net
["external"]:
2077 net_name
= sce_net
["name"]
2078 if "netmap-use" in site
or "netmap-create" in site
:
2079 create_network
= False
2080 lookfor_network
= False
2081 if "netmap-use" in site
:
2082 lookfor_network
= True
2083 if utils
.check_valid_uuid(site
["netmap-use"]):
2084 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2085 lookfor_filter
["id"] = site
["netmap-use"]
2087 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2088 lookfor_filter
["name"] = site
["netmap-use"]
2089 if "netmap-create" in site
:
2090 create_network
= True
2091 net_vim_name
= net_name
2092 if site
["netmap-create"]:
2093 net_vim_name
= site
["netmap-create"]
2095 elif sce_net
['vim_id'] != None:
2096 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
2097 create_network
= False
2098 lookfor_network
= True
2099 lookfor_filter
["id"] = sce_net
['vim_id']
2100 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
2101 #look for network at datacenter and return error
2103 #There is not a netmap, look at datacenter for a net with this name and create if not found
2104 create_network
= True
2105 lookfor_network
= True
2106 lookfor_filter
["name"] = sce_net
["name"]
2107 net_vim_name
= sce_net
["name"]
2108 filter_text
= "scenario name '%s'" % sce_net
["name"]
2111 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
2112 net_name
= net_name
[:255] #limit length
2113 net_vim_name
= net_name
2114 create_network
= True
2115 lookfor_network
= False
2118 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
2119 if len(vim_nets
) > 1:
2120 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2121 elif len(vim_nets
) == 0:
2122 if not create_network
:
2123 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2125 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
2126 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
2127 create_network
= False
2129 #if network is not external
2130 task
= new_task("new-net", (net_vim_name
, net_type
, sce_net
.get('ip_profile',None)))
2131 task_id
= task
["id"]
2132 instance_tasks
[task_id
] = task
2133 tasks_to_launch
[myvim_thread_id
].append(task
)
2134 #network_id = vim.new_network(net_vim_name, net_type, sce_net.get('ip_profile',None))
2135 sce_net
["vim_id_sites"][datacenter_id
] = task_id
2136 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = task_id
2137 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':task_id
})
2138 sce_net
["created"] = True
2140 # 2. Creating new nets (vnf internal nets) in the VIM"
2141 #For each vnf net, we create it and we add it to instanceNetlist.
2142 for sce_vnf
in scenarioDict
['vnfs']:
2143 for net
in sce_vnf
['nets']:
2144 if sce_vnf
.get("datacenter"):
2145 vim
= myvims
[ sce_vnf
["datacenter"] ]
2146 datacenter_id
= sce_vnf
["datacenter"]
2147 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"]]
2149 vim
= myvims
[ default_datacenter_id
]
2150 datacenter_id
= default_datacenter_id
2151 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2152 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
2153 net_name
= descriptor_net
.get("name")
2155 net_name
= "%s.%s" %(instance_name
, net
["name"])
2156 net_name
= net_name
[:255] #limit length
2157 net_type
= net
['type']
2158 task
= new_task("new-net", (net_name
, net_type
, net
.get('ip_profile',None)))
2159 task_id
= task
["id"]
2160 instance_tasks
[task_id
] = task
2161 tasks_to_launch
[myvim_thread_id
].append(task
)
2162 # network_id = vim.new_network(net_name, net_type, net.get('ip_profile',None))
2163 net
['vim_id'] = task_id
2164 if sce_vnf
['uuid'] not in auxNetDict
:
2165 auxNetDict
[sce_vnf
['uuid']] = {}
2166 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = task_id
2167 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':task_id
})
2168 net
["created"] = True
2171 #print "auxNetDict:"
2172 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2174 # 3. Creating new vm instances in the VIM
2175 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2176 for sce_vnf
in scenarioDict
['vnfs']:
2177 if sce_vnf
.get("datacenter"):
2178 vim
= myvims
[ sce_vnf
["datacenter"] ]
2179 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"] ]
2180 datacenter_id
= sce_vnf
["datacenter"]
2182 vim
= myvims
[ default_datacenter_id
]
2183 myvim_thread_id
= myvim_threads_id
[ default_datacenter_id
]
2184 datacenter_id
= default_datacenter_id
2185 sce_vnf
["datacenter_id"] = datacenter_id
2187 for vm
in sce_vnf
['vms']:
2190 myVMDict
['name'] = "{}.{}.{}".format(instance_name
,sce_vnf
['name'],chr(96+i
))
2191 myVMDict
['description'] = myVMDict
['name'][0:99]
2193 # myVMDict['start'] = "no"
2194 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2195 #create image at vim in case it not exist
2196 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2197 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2198 vm
['vim_image_id'] = image_id
2200 #create flavor at vim in case it not exist
2201 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2202 if flavor_dict
['extended']!=None:
2203 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2204 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
2206 #Obtain information for additional disks
2207 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
2208 if not extended_flavor_dict
:
2209 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
2212 #extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
2213 myVMDict
['disks'] = None
2214 extended_info
= extended_flavor_dict
[0]['extended']
2215 if extended_info
!= None:
2216 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
2217 if 'disks' in extended_flavor_dict_yaml
:
2218 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
2220 vm
['vim_flavor_id'] = flavor_id
2221 myVMDict
['imageRef'] = vm
['vim_image_id']
2222 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2223 myVMDict
['networks'] = []
2225 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
2226 for iface
in vm
['interfaces']:
2228 if iface
['type']=="data":
2229 netDict
['type'] = iface
['model']
2230 elif "model" in iface
and iface
["model"]!=None:
2231 netDict
['model']=iface
['model']
2232 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2233 #discover type of interface looking at flavor
2234 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2235 for flavor_iface
in numa
.get('interfaces',[]):
2236 if flavor_iface
.get('name') == iface
['internal_name']:
2237 if flavor_iface
['dedicated'] == 'yes':
2238 netDict
['type']="PF" #passthrough
2239 elif flavor_iface
['dedicated'] == 'no':
2240 netDict
['type']="VF" #siov
2241 elif flavor_iface
['dedicated'] == 'yes:sriov':
2242 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2243 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2245 netDict
["use"]=iface
['type']
2246 if netDict
["use"]=="data" and not netDict
.get("type"):
2247 #print "netDict", netDict
2248 #print "iface", iface
2249 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'])
2250 if flavor_dict
.get('extended')==None:
2251 raise NfvoException(e_text
+ "After database migration some information is not available. \
2252 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2254 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2255 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2256 netDict
["type"]="virtual"
2257 if "vpci" in iface
and iface
["vpci"] is not None:
2258 netDict
['vpci'] = iface
['vpci']
2259 if "mac" in iface
and iface
["mac"] is not None:
2260 netDict
['mac_address'] = iface
['mac']
2261 if "port-security" in iface
and iface
["port-security"] is not None:
2262 netDict
['port_security'] = iface
['port-security']
2263 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2264 netDict
['floating_ip'] = iface
['floating-ip']
2265 netDict
['name'] = iface
['internal_name']
2266 if iface
['net_id'] is None:
2267 for vnf_iface
in sce_vnf
["interfaces"]:
2270 if vnf_iface
['interface_id']==iface
['uuid']:
2271 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
2274 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2275 if netDict
.get('net_id') and is_task_id(netDict
['net_id']):
2276 task_depends
[netDict
['net_id']] = instance_tasks
[netDict
['net_id']]
2277 #skip bridge ifaces not connected to any net
2278 #if 'net_id' not in netDict or netDict['net_id']==None:
2280 myVMDict
['networks'].append(netDict
)
2281 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2282 #print myVMDict['name']
2283 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2284 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2285 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2286 if vm
.get("boot_data"):
2287 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
2289 cloud_config_vm
= cloud_config
2290 task
= new_task("new-vm", (myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2291 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2292 cloud_config_vm
, myVMDict
['disks']), depends
=task_depends
)
2293 instance_tasks
[task
["id"]] = task
2294 tasks_to_launch
[myvim_thread_id
].append(task
)
2296 vm
['vim_id'] = vm_id
2297 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2298 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2299 for net
in myVMDict
['networks']:
2301 for iface
in vm
['interfaces']:
2302 if net
["name"]==iface
["internal_name"]:
2303 iface
["vim_id"]=net
["vim_id"]
2305 scenarioDict
["datacenter2tenant"] = myvim_threads_id
2306 logger
.debug("create_instance Deployment done scenarioDict: %s",
2307 yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False) )
2308 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
2309 for myvim_thread_id
,task_list
in tasks_to_launch
.items():
2310 for task
in task_list
:
2311 vim_threads
["running"][myvim_thread_id
].insert_task(task
)
2313 global_instance_tasks
[instance_id
] = instance_tasks
2314 # Update database with those ended instance_tasks
2315 # for task in instance_tasks.values():
2316 # if task["status"] == "ok":
2317 # if task["name"] == "new-vm":
2318 # mydb.update_rows("instance_vms", UPDATE={"vim_vm_id": task["result"]},
2319 # WHERE={"vim_vm_id": task["id"]})
2320 # elif task["name"] == "new-net":
2321 # mydb.update_rows("instance_nets", UPDATE={"vim_net_id": task["result"]},
2322 # WHERE={"vim_net_id": task["id"]})
2323 return mydb
.get_instance_scenario(instance_id
)
2324 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2325 message
= rollback(mydb
, myvims
, rollbackList
)
2326 if isinstance(e
, db_base_Exception
):
2327 error_text
= "database Exception"
2328 elif isinstance(e
, vimconn
.vimconnException
):
2329 error_text
= "VIM Exception"
2331 error_text
= "Exception"
2332 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2333 #logger.error("create_instance: %s", error_text)
2334 raise NfvoException(error_text
, e
.http_code
)
2337 def delete_instance(mydb
, tenant_id
, instance_id
):
2338 #print "Checking that the instance_id exists and getting the instance dictionary"
2339 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2340 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2341 tenant_id
= instanceDict
["tenant_id"]
2342 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2344 #1. Delete from Database
2345 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2354 for sce_vnf
in instanceDict
['vnfs']:
2355 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2356 if datacenter_key
not in myvims
:
2358 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2359 except NfvoException
as e
:
2360 logger
.error(str(e
))
2362 myvim_threads
[datacenter_key
] = myvim_thread
2363 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2364 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2366 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2367 sce_vnf
["datacenter_tenant_id"]))
2368 myvims
[datacenter_key
] = None
2370 myvims
[datacenter_key
] = vims
.values()[0]
2371 myvim
= myvims
[datacenter_key
]
2372 myvim_thread
= myvim_threads
[datacenter_key
]
2373 for vm
in sce_vnf
['vms']:
2375 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2379 if is_task_id(vm
['vim_vm_id']):
2380 task_id
= vm
['vim_vm_id']
2381 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2383 error_msg
+= "\n VM was scheduled for create, but task {} is not found".format(task_id
)
2386 if old_task
["status"] == "enqueued":
2387 old_task
["status"] = "deleted"
2388 elif old_task
["status"] == "error":
2390 elif old_task
["status"] == "processing":
2391 task
= new_task("del-vm", (task_id
, vm
["interfaces"]), depends
={task_id
: old_task
})
2393 task
= new_task("del-vm", (old_task
["result"], vm
["interfaces"]))
2395 task
= new_task("del-vm", (vm
['vim_vm_id'], vm
["interfaces"]) )
2397 myvim_thread
.insert_task(task
)
2398 except vimconn
.vimconnNotFoundException
as e
:
2399 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2400 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2401 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2402 except vimconn
.vimconnException
as e
:
2403 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2404 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2405 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2409 for net
in instanceDict
['nets']:
2410 if not net
['created']:
2411 continue #skip not created nets
2412 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2413 if datacenter_key
not in myvims
:
2415 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2416 except NfvoException
as e
:
2417 logger
.error(str(e
))
2419 myvim_threads
[datacenter_key
] = myvim_thread
2420 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2421 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2423 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2424 myvims
[datacenter_key
] = None
2426 myvims
[datacenter_key
] = vims
.values()[0]
2427 myvim
= myvims
[datacenter_key
]
2428 myvim_thread
= myvim_threads
[datacenter_key
]
2431 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2435 if is_task_id(net
['vim_net_id']):
2436 task_id
= net
['vim_net_id']
2437 old_task
= global_instance_tasks
[instance_id
].get(task_id
)
2439 error_msg
+= "\n NET was scheduled for create, but task {} is not found".format(task_id
)
2442 if old_task
["status"] == "enqueued":
2443 old_task
["status"] = "deleted"
2444 elif old_task
["status"] == "error":
2446 elif old_task
["status"] == "processing":
2447 task
= new_task("del-net", task_id
, depends
={task_id
: old_task
})
2449 task
= new_task("del-net", old_task
["result"])
2451 task
= new_task("del-net", (net
['vim_net_id'], net
['sdn_net_id']))
2453 myvim_thread
.insert_task(task
)
2454 except vimconn
.vimconnNotFoundException
as e
:
2455 error_msg
+= "\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2456 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2457 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2458 except vimconn
.vimconnException
as e
:
2459 error_msg
+= "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'],
2460 net
["datacenter_id"],
2461 e
.http_code
, str(e
))
2462 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2463 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2464 if len(error_msg
) > 0:
2465 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2467 return 'instance ' + message
+ ' deleted'
2470 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2471 '''Refreshes a scenario instance. It modifies instanceDict'''
2473 - 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
2476 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2477 # #print "nfvo.refresh_instance begins"
2478 # #print json.dumps(instanceDict, indent=4)
2480 # #print "Getting the VIM URL and the VIM tenant_id"
2483 # # 1. Getting VIM vm and net list
2484 # vms_updated = [] #List of VM instance uuids in openmano that were updated
2487 # for sce_vnf in instanceDict['vnfs']:
2488 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
2489 # if datacenter_key not in vm_list:
2490 # vm_list[datacenter_key] = []
2491 # if datacenter_key not in myvims:
2492 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
2493 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
2494 # if len(vims) == 0:
2495 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
2496 # myvims[datacenter_key] = None
2498 # myvims[datacenter_key] = vims.values()[0]
2499 # for vm in sce_vnf['vms']:
2500 # vm_list[datacenter_key].append(vm['vim_vm_id'])
2501 # vms_notupdated.append(vm["uuid"])
2503 # nets_updated = [] #List of VM instance uuids in openmano that were updated
2504 # nets_notupdated=[]
2506 # for net in instanceDict['nets']:
2507 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
2508 # if datacenter_key not in net_list:
2509 # net_list[datacenter_key] = []
2510 # if datacenter_key not in myvims:
2511 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
2512 # datacenter_tenant_id=net["datacenter_tenant_id"])
2513 # if len(vims) == 0:
2514 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
2515 # myvims[datacenter_key] = None
2517 # myvims[datacenter_key] = vims.values()[0]
2519 # net_list[datacenter_key].append(net['vim_net_id'])
2520 # nets_notupdated.append(net["uuid"])
2522 # # 1. Getting the status of all VMs
2524 # for datacenter_key in myvims:
2525 # if not vm_list.get(datacenter_key):
2529 # if not myvims[datacenter_key]:
2530 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2533 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
2535 # except vimconn.vimconnException as e:
2536 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2537 # failed_message = str(e)
2539 # for vm in vm_list[datacenter_key]:
2540 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2542 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2543 # for sce_vnf in instanceDict['vnfs']:
2544 # for vm in sce_vnf['vms']:
2545 # vm_id = vm['vim_vm_id']
2546 # interfaces = vm_dict[vm_id].pop('interfaces', [])
2547 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2548 # has_mgmt_iface = False
2549 # for iface in vm["interfaces"]:
2550 # if iface["type"]=="mgmt":
2551 # has_mgmt_iface = True
2552 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
2553 # vm_dict[vm_id]['status'] = "ACTIVE"
2554 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
2555 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
2556 # 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'):
2557 # vm['status'] = vm_dict[vm_id]['status']
2558 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
2559 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
2560 # # 2.1. Update in openmano DB the VMs whose status changed
2562 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
2563 # vms_notupdated.remove(vm["uuid"])
2565 # vms_updated.append(vm["uuid"])
2566 # except db_base_Exception as e:
2567 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2568 # # 2.2. Update in openmano DB the interface VMs
2569 # for interface in interfaces:
2570 # #translate from vim_net_id to instance_net_id
2571 # network_id_list=[]
2572 # for net in instanceDict['nets']:
2573 # if net["vim_net_id"] == interface["vim_net_id"]:
2574 # network_id_list.append(net["uuid"])
2575 # if not network_id_list:
2577 # del interface["vim_net_id"]
2579 # for network_id in network_id_list:
2580 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
2581 # except db_base_Exception as e:
2582 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
2584 # # 3. Getting the status of all nets
2586 # for datacenter_key in myvims:
2587 # if not net_list.get(datacenter_key):
2590 # failed_message = ""
2591 # if not myvims[datacenter_key]:
2592 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
2595 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
2597 # except vimconn.vimconnException as e:
2598 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
2599 # failed_message = str(e)
2601 # for net in net_list[datacenter_key]:
2602 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
2604 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2605 # # TODO: update nets inside a vnf
2606 # for net in instanceDict['nets']:
2607 # net_id = net['vim_net_id']
2608 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
2609 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
2610 # 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'):
2611 # net['status'] = net_dict[net_id]['status']
2612 # net['error_msg'] = net_dict[net_id].get('error_msg')
2613 # net['vim_info'] = net_dict[net_id].get('vim_info')
2614 # # 5.1. Update in openmano DB the nets whose status changed
2616 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
2617 # nets_notupdated.remove(net["uuid"])
2619 # nets_updated.append(net["uuid"])
2620 # except db_base_Exception as e:
2621 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
2623 # # Returns appropriate output
2624 # #print "nfvo.refresh_instance finishes"
2625 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2626 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
2627 instance_id
= instanceDict
['uuid']
2628 # if len(vms_notupdated)+len(nets_notupdated)>0:
2629 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
2630 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
2632 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2635 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2636 #print "Checking that the instance_id exists and getting the instance dictionary"
2637 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2638 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2640 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2641 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2643 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2644 myvim
= vims
.values()[0]
2647 input_vnfs
= action_dict
.pop("vnfs", [])
2648 input_vms
= action_dict
.pop("vms", [])
2649 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2653 for sce_vnf
in instanceDict
['vnfs']:
2654 for vm
in sce_vnf
['vms']:
2655 if not action_over_all
:
2656 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2657 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2660 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2661 if "console" in action_dict
:
2662 if not global_config
["http_console_proxy"]:
2663 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2664 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2665 protocol
=data
["protocol"],
2666 ip
= data
["server"],
2667 port
= data
["port"],
2668 suffix
= data
["suffix"]),
2672 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2673 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2674 "description": "this console is only reachable by local interface",
2679 #print "console data", data
2681 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2682 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2683 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2684 protocol
=data
["protocol"],
2685 ip
= global_config
["http_console_host"],
2686 port
= console_thread
.port
,
2687 suffix
= data
["suffix"]),
2691 except NfvoException
as e
:
2692 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2696 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2698 except vimconn
.vimconnException
as e
:
2699 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2702 if vm_ok
==0: #all goes wrong
2708 def create_or_use_console_proxy_thread(console_server
, console_port
):
2709 #look for a non-used port
2710 console_thread_key
= console_server
+ ":" + str(console_port
)
2711 if console_thread_key
in global_config
["console_thread"]:
2712 #global_config["console_thread"][console_thread_key].start_timeout()
2713 return global_config
["console_thread"][console_thread_key
]
2715 for port
in global_config
["console_port_iterator"]():
2716 #print "create_or_use_console_proxy_thread() port:", port
2717 if port
in global_config
["console_ports"]:
2720 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2722 global_config
["console_thread"][console_thread_key
] = clithread
2723 global_config
["console_ports"][port
] = console_thread_key
2725 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2726 #port used, try with onoher
2728 except cli
.ConsoleProxyException
as e
:
2729 raise NfvoException(str(e
), HTTP_Bad_Request
)
2730 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2733 def check_tenant(mydb
, tenant_id
):
2734 '''check that tenant exists at database'''
2735 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2737 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2741 def new_tenant(mydb
, tenant_dict
):
2742 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2746 def delete_tenant(mydb
, tenant
):
2747 #get nfvo_tenant info
2749 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2750 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2751 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2754 def new_datacenter(mydb
, datacenter_descriptor
):
2755 if "config" in datacenter_descriptor
:
2756 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2757 #Check that datacenter-type is correct
2758 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2761 module
= "vimconn_" + datacenter_type
2762 pkg
= __import__("osm_ro." + module
)
2763 vim_conn
= getattr(pkg
, module
)
2764 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
2765 except (IOError, ImportError):
2766 # if module_info and module_info[0]:
2767 # file.close(module_info[0])
2768 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2770 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2771 return datacenter_id
2774 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2775 #obtain data, check that only one exist
2776 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2778 datacenter_id
= datacenter
['uuid']
2779 where
={'uuid': datacenter
['uuid']}
2780 if "config" in datacenter_descriptor
:
2781 if datacenter_descriptor
['config']!=None:
2783 new_config_dict
= datacenter_descriptor
["config"]
2786 for k
in new_config_dict
:
2787 if new_config_dict
[k
]==None:
2790 config_text
= datacenter
.get("config")
2793 config_dict
= yaml
.load(config_text
)
2794 config_dict
.update(new_config_dict
)
2798 except Exception as e
:
2799 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2800 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2801 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2802 return datacenter_id
2805 def delete_datacenter(mydb
, datacenter
):
2806 #get nfvo_tenant info
2807 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2808 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2809 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2812 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):
2813 #get datacenter info
2814 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
, vim_passwd
=vim_password
)
2815 datacenter_name
= myvim
["name"]
2817 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
2819 # get nfvo_tenant info
2820 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2821 if vim_tenant_name
==None:
2822 vim_tenant_name
=tenant_dict
['name']
2824 #check that this association does not exist before
2825 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2826 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2827 if len(tenants_datacenters
)>0:
2828 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2830 vim_tenant_id_exist_atdb
=False
2831 if not create_vim_tenant
:
2832 where_
={"datacenter_id": datacenter_id
}
2833 if vim_tenant_id
!=None:
2834 where_
["vim_tenant_id"] = vim_tenant_id
2835 if vim_tenant_name
!=None:
2836 where_
["vim_tenant_name"] = vim_tenant_name
2837 #check if vim_tenant_id is already at database
2838 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2839 if len(datacenter_tenants_dict
)>=1:
2840 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2841 vim_tenant_id_exist_atdb
=True
2842 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2844 datacenter_tenants_dict
= {}
2845 #insert at table datacenter_tenants
2846 else: #if vim_tenant_id==None:
2847 #create tenant at VIM if not provided
2849 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2850 except vimconn
.vimconnException
as e
:
2851 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2852 datacenter_tenants_dict
= {}
2853 datacenter_tenants_dict
["created"]="true"
2855 #fill datacenter_tenants table
2856 if not vim_tenant_id_exist_atdb
:
2857 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2858 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2859 datacenter_tenants_dict
["user"] = vim_username
2860 datacenter_tenants_dict
["passwd"] = vim_password
2861 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2863 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
2864 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2865 datacenter_tenants_dict
["uuid"] = id_
2867 #fill tenants_datacenters table
2868 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
2869 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
2870 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2872 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
2873 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
2874 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
2875 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
2877 thread_id
= datacenter_tenants_dict
["uuid"]
2878 vim_threads
["running"][thread_id
] = new_thread
2879 return datacenter_id
2882 def edit_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=None, vim_tenant_name
=None,
2883 vim_username
=None, vim_password
=None, config
=None):
2884 #Obtain the data of this datacenter_tenant_id
2885 vim_data
= mydb
.get_rows(
2886 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
2887 "datacenter_tenants.passwd", "datacenter_tenants.config"),
2888 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
2889 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
2890 "tenants_datacenters.datacenter_id": datacenter_id
})
2892 logger
.debug(str(vim_data
))
2893 if len(vim_data
) < 1:
2894 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
2898 v
['config'] = yaml
.load(v
['config'])
2901 v
['vim_tenant_id'] = vim_tenant_id
2903 v
['vim_tenant_name'] = vim_tenant_name
2905 v
['user'] = vim_username
2907 v
['passwd'] = vim_password
2911 v
['config'].update(config
)
2913 logger
.debug(str(v
))
2914 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
2915 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
2916 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
2918 return datacenter_id
2920 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2921 #get datacenter info
2922 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2924 #get nfvo_tenant info
2925 if not tenant_id
or tenant_id
=="any":
2928 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2929 tenant_uuid
= tenant_dict
['uuid']
2931 #check that this association exist before
2932 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2934 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2935 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2936 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2937 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2939 #delete this association
2940 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2942 #get vim_tenant info and deletes
2944 for tenant_datacenter_item
in tenant_datacenter_list
:
2945 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2946 #try to delete vim:tenant
2948 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2949 if vim_tenant_dict
['created']=='true':
2950 #delete tenant at VIM if created by NFVO
2952 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2953 except vimconn
.vimconnException
as e
:
2954 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2955 logger
.warn(warning
)
2956 except db_base_Exception
as e
:
2957 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2958 pass # the error will be caused because dependencies, vim_tenant can not be deleted
2959 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
2960 thread
= vim_threads
["running"][thread_id
]
2961 thread
.insert_task(new_task("exit", None))
2962 vim_threads
["deleting"][thread_id
] = thread
2963 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2966 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2968 #get datacenter info
2969 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2971 if 'net-update' in action_dict
:
2973 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2975 except vimconn
.vimconnException
as e
:
2976 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2977 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2978 #update nets Change from VIM format to NFVO format
2981 net_nfvo
={'datacenter_id': datacenter_id
}
2982 net_nfvo
['name'] = net
['name']
2983 #net_nfvo['description']= net['name']
2984 net_nfvo
['vim_net_id'] = net
['id']
2985 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2986 net_nfvo
['shared'] = net
['shared']
2987 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2988 net_list
.append(net_nfvo
)
2989 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2990 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2992 elif 'net-edit' in action_dict
:
2993 net
= action_dict
['net-edit'].pop('net')
2994 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2995 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2996 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2998 elif 'net-delete' in action_dict
:
2999 net
= action_dict
['net-deelte'].get('net')
3000 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3001 result
= mydb
.delete_row(FROM
='datacenter_nets',
3002 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3006 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
3009 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
3010 #get datacenter info
3011 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3013 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
3014 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
3015 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
3019 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
3020 #get datacenter info
3021 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3024 action_dict
= action_dict
["netmap"]
3025 if 'vim_id' in action_dict
:
3026 filter_dict
["id"] = action_dict
['vim_id']
3027 if 'vim_name' in action_dict
:
3028 filter_dict
["name"] = action_dict
['vim_name']
3030 filter_dict
["shared"] = True
3033 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
3034 except vimconn
.vimconnException
as e
:
3035 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
3036 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3037 if len(vim_nets
)>1 and action_dict
:
3038 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
3039 elif len(vim_nets
)==0: # and action_dict:
3040 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
3042 for net
in vim_nets
:
3043 net_nfvo
={'datacenter_id': datacenter_id
}
3044 if action_dict
and "name" in action_dict
:
3045 net_nfvo
['name'] = action_dict
['name']
3047 net_nfvo
['name'] = net
['name']
3048 #net_nfvo['description']= net['name']
3049 net_nfvo
['vim_net_id'] = net
['id']
3050 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3051 net_nfvo
['shared'] = net
['shared']
3052 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3054 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
3055 net_nfvo
["status"] = "OK"
3056 net_nfvo
["uuid"] = net_id
3057 except db_base_Exception
as e
:
3061 net_nfvo
["status"] = "FAIL: " + str(e
)
3062 net_list
.append(net_nfvo
)
3066 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
3067 #get datacenter info
3068 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3071 if utils
.check_valid_uuid(name
):
3072 filter_dict
["id"] = name
3074 filter_dict
["name"] = name
3076 if item
=="networks":
3077 #filter_dict['tenant_id'] = myvim['tenant_id']
3078 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
3079 elif item
=="tenants":
3080 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
3081 elif item
== "images":
3082 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
3084 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3085 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
3086 if name
and len(content
)==1:
3087 return {item
[:-1]: content
[0]}
3088 elif name
and len(content
)==0:
3089 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
3092 return {item
: content
}
3093 except vimconn
.vimconnException
as e
:
3094 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
3095 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
3098 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
3099 #get datacenter info
3100 if tenant_id
== "any":
3103 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3105 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
3106 logger
.debug("vim_action_delete vim response: " + str(content
))
3107 items
= content
.values()[0]
3108 if type(items
)==list and len(items
)==0:
3109 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
3110 elif type(items
)==list and len(items
)>1:
3111 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
3112 else: # it is a dict
3113 item_id
= items
["id"]
3114 item_name
= str(items
.get("name"))
3117 if item
=="networks":
3118 content
= myvim
.delete_network(item_id
)
3119 elif item
=="tenants":
3120 content
= myvim
.delete_tenant(item_id
)
3121 elif item
== "images":
3122 content
= myvim
.delete_image(item_id
)
3124 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3125 except vimconn
.vimconnException
as e
:
3126 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
3127 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
3129 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
3132 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
3133 #get datacenter info
3134 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
3135 if tenant_id
== "any":
3137 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3139 if item
=="networks":
3140 net
= descriptor
["network"]
3141 net_name
= net
.pop("name")
3142 net_type
= net
.pop("type", "bridge")
3143 net_public
= net
.pop("shared", False)
3144 net_ipprofile
= net
.pop("ip_profile", None)
3145 net_vlan
= net
.pop("vlan", None)
3146 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
3147 elif item
=="tenants":
3148 tenant
= descriptor
["tenant"]
3149 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
3151 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3152 except vimconn
.vimconnException
as e
:
3153 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
3155 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
3157 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
3158 data
= ovim
.new_of_controller(sdn_controller
)
3159 logger
.debug('New SDN controller created with uuid {}'.format(data
))
3162 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
3163 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
3164 msg
= 'SDN controller {} updated'.format(data
)
3168 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
3169 if controller_id
== None:
3170 data
= ovim
.get_of_controllers()
3172 data
= ovim
.show_of_controller(controller_id
)
3174 msg
= 'SDN controller list:\n {}'.format(data
)
3178 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
3179 select_
= ('uuid', 'config')
3180 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
3181 for datacenter
in datacenters
:
3182 if datacenter
['config']:
3183 config
= yaml
.load(datacenter
['config'])
3184 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
3185 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
3187 data
= ovim
.delete_of_controller(controller_id
)
3188 msg
= 'SDN controller {} deleted'.format(data
)
3192 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
3193 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
3194 if len(controller
) < 1:
3195 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
3198 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
3200 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
3202 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
3203 switch_dpid
= sdn_controller
["dpid"]
3206 for compute_node
in sdn_port_mapping
:
3207 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
3209 element
["compute_node"] = compute_node
["compute_node"]
3210 for port
in compute_node
["ports"]:
3211 element
["pci"] = port
.get("pci")
3212 element
["switch_port"] = port
.get("switch_port")
3213 element
["switch_mac"] = port
.get("switch_mac")
3214 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
3215 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
3216 " or 'switch_mac'", HTTP_Bad_Request
)
3217 maps
.append(dict(element
))
3219 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
3221 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
3222 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
3225 "sdn-controller": None,
3226 "datacenter-id": datacenter_id
,
3228 "ports_mapping": list()
3231 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
3232 if datacenter
['config']:
3233 config
= yaml
.load(datacenter
['config'])
3234 if 'sdn-controller' in config
:
3235 controller_id
= config
['sdn-controller']
3236 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
3237 result
["sdn-controller"] = controller_id
3238 result
["dpid"] = sdn_controller
["dpid"]
3240 if result
["sdn-controller"] == None or result
["dpid"] == None:
3241 raise NfvoException("Not all SDN controller information for datacenter {} could be found: {}".format(datacenter_id
, result
),
3242 HTTP_Internal_Server_Error
)
3247 ports_correspondence_dict
= dict()
3249 if result
["sdn-controller"] != link
["ofc_id"]:
3250 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
3251 if result
["dpid"] != link
["switch_dpid"]:
3252 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
3254 element
["pci"] = link
["pci"]
3255 if link
["switch_port"]:
3256 element
["switch_port"] = link
["switch_port"]
3257 if link
["switch_mac"]:
3258 element
["switch_mac"] = link
["switch_mac"]
3260 if not link
["compute_node"] in ports_correspondence_dict
:
3262 content
["compute_node"] = link
["compute_node"]
3263 content
["ports"] = list()
3264 ports_correspondence_dict
[link
["compute_node"]] = content
3266 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
3268 for key
in sorted(ports_correspondence_dict
):
3269 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
3273 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
3274 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})