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 #import openvim.ovim as Ovim
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')
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
, store
=True, depends
=None):
83 task_id
= get_task_id()
84 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
86 task
["depends"] = depends
88 task_dict
[task_id
] = task
93 return True if id[:5] == "TASK." else False
96 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
97 name
= datacenter_name
[:16]
98 if name
not in vim_threads
["names"]:
99 vim_threads
["names"].append(name
)
101 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
102 if name
not in vim_threads
["names"]:
103 vim_threads
["names"].append(name
)
105 name
= datacenter_id
+ "-" + tenant_id
106 vim_threads
["names"].append(name
)
110 def start_service(mydb
):
111 global db
, global_config
112 db
= nfvo_db
.nfvo_db()
113 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
116 # Initialize openvim for SDN control
117 # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
118 # TODO: review ovim.py to delete not needed configuration
119 ovim_configuration
= {
120 'logger_name': 'openvim',
121 'network_vlan_range_start': 1000,
122 'network_vlan_range_end': 4096,
123 'log_level_db': 'DEBUG',
124 'db_name': 'mano_vim_db',
125 'db_host': 'localhost',
127 'db_passwd': 'vimpw',
128 'database_version': '0.15',
131 'of_controller_nets_with_same_vlan': True,
132 'network_type': 'bridge',
133 #TODO: log_level_of should not be needed. To be modified in ovim
134 'log_level_of': 'DEBUG'
136 #ovim = Ovim.ovim(ovim_configuration)
137 #ovim.start_service()
139 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'
140 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
141 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
142 'user','passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
144 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
146 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
148 extra
.update(yaml
.load(vim
["config"]))
149 if vim
.get('dt_config'):
150 extra
.update(yaml
.load(vim
["dt_config"]))
151 if vim
["type"] not in vimconn_imported
:
154 module
= "vimconn_" + vim
["type"]
155 module_info
= imp
.find_module(module
)
156 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
157 vimconn_imported
[vim
["type"]] = vim_conn
158 except (IOError, ImportError) as e
:
159 if module_info
and module_info
[0]:
160 file.close(module_info
[0])
161 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
162 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
164 thread_id
= vim
["datacenter_id"] + "." + vim
['nfvo_tenant_id']
165 vim_persistent_info
[thread_id
] = {}
168 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
169 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
170 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
171 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
172 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
173 user
=vim
['user'], passwd
=vim
['passwd'],
174 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
176 except Exception as e
:
177 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
178 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['vim_tenant_id'], vim
['vim_tenant_name'], vim
['vim_tenant_id'])
179 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, vim
['datacenter_name'],
180 vim
.get('datacenter_tenant_id'), db
=db
, db_lock
=db_lock
, ovim
=ovim
)
182 vim_threads
["running"][thread_id
] = new_thread
183 except db_base_Exception
as e
:
184 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
187 global ovim
, global_config
190 for thread_id
,thread
in vim_threads
["running"].items():
191 thread
.insert_task(new_task("exit", None, store
=False))
192 vim_threads
["deleting"][thread_id
] = thread
193 vim_threads
["running"] = {}
194 if global_config
and global_config
.get("console_thread"):
195 for thread
in global_config
["console_thread"]:
196 thread
.terminate
= True
199 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
201 return result, content:
202 <0, error_text upon error
203 nb_records, flavor_list on success
206 WHERE_dict
['vnf_id'] = vnf_id
207 if nfvo_tenant
is not None:
208 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
210 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
211 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
212 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
213 #print "get_flavor_list result:", result
214 #print "get_flavor_list content:", content
216 for flavor
in flavors
:
217 flavorList
.append(flavor
['flavor_id'])
221 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
223 return result, content:
224 <0, error_text upon error
225 nb_records, flavor_list on success
228 WHERE_dict
['vnf_id'] = vnf_id
229 if nfvo_tenant
is not None:
230 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
232 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
233 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
236 imageList
.append(image
['image_id'])
240 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
241 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
242 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
243 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
244 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
245 raise exception upon error
248 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
249 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
250 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
251 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
252 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
253 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
254 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
255 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'
256 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
257 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
258 'user','passwd', 'dt.config as dt_config')
260 from_
= 'datacenters as d'
261 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
263 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
266 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id')}
268 extra
.update(yaml
.load(vim
["config"]))
269 if vim
.get('dt_config'):
270 extra
.update(yaml
.load(vim
["dt_config"]))
271 if vim
["type"] not in vimconn_imported
:
274 module
= "vimconn_" + vim
["type"]
275 module_info
= imp
.find_module(module
)
276 vim_conn
= imp
.load_module(vim
["type"], *module_info
)
277 vimconn_imported
[vim
["type"]] = vim_conn
278 except (IOError, ImportError) as e
:
279 if module_info
and module_info
[0]:
280 file.close(module_info
[0])
281 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
282 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
285 if 'nfvo_tenant_id' in vim
:
286 thread_id
= vim
["datacenter_id"] + "." + vim
['nfvo_tenant_id']
287 if thread_id
not in vim_persistent_info
:
288 vim_persistent_info
[thread_id
] = {}
289 persistent_info
= vim_persistent_info
[thread_id
]
293 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
294 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
295 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
296 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
297 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
298 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
299 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
300 config
=extra
, persistent_info
=persistent_info
302 except Exception as e
:
303 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
305 except db_base_Exception
as e
:
306 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
309 def rollback(mydb
, vims
, rollback_list
):
311 #delete things by reverse order
312 for i
in range(len(rollback_list
)-1, -1, -1):
313 item
= rollback_list
[i
]
314 if item
["where"]=="vim":
315 if item
["vim_id"] not in vims
:
317 vim
=vims
[ item
["vim_id"] ]
319 if item
["what"]=="image":
320 vim
.delete_image(item
["uuid"])
321 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
322 elif item
["what"]=="flavor":
323 vim
.delete_flavor(item
["uuid"])
324 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
325 elif item
["what"]=="network":
326 vim
.delete_network(item
["uuid"])
327 elif item
["what"]=="vm":
328 vim
.delete_vminstance(item
["uuid"])
329 except vimconn
.vimconnException
as e
:
330 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
331 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
332 except db_base_Exception
as e
:
333 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
337 if item
["what"]=="image":
338 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
339 elif item
["what"]=="flavor":
340 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
341 except db_base_Exception
as e
:
342 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
343 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
344 if len(undeleted_items
)==0:
345 return True," Rollback successful."
347 return False," Rollback fails to delete: " + str(undeleted_items
)
350 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
352 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
354 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
356 #dataplane interfaces
357 for numa
in vnfc
.get("numas",() ):
358 for interface
in numa
.get("interfaces",()):
359 if interface
["name"] in name_dict
:
361 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
362 vnfc
["name"], interface
["name"]),
364 name_dict
[ interface
["name"] ] = "underlay"
366 for interface
in vnfc
.get("bridge-ifaces",() ):
367 if interface
["name"] in name_dict
:
369 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
370 vnfc
["name"], interface
["name"]),
372 name_dict
[ interface
["name"] ] = "overlay"
373 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
374 # check bood-data info
375 if "boot-data" in vnfc
:
376 # check that user-data is incompatible with users and config-files
377 if (vnfc
["boot-data"].get("users") or vnfc
["boot-data"].get("config-files")) and vnfc
["boot-data"].get("user-data"):
379 "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
382 #check if the info in external_connections matches with the one in the vnfcs
384 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
385 if external_connection
["name"] in name_list
:
387 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
388 external_connection
["name"]),
390 name_list
.append(external_connection
["name"])
391 if external_connection
["VNFC"] not in vnfc_interfaces
:
393 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
394 external_connection
["name"], external_connection
["VNFC"]),
397 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
399 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
400 external_connection
["name"],
401 external_connection
["local_iface_name"]),
404 #check if the info in internal_connections matches with the one in the vnfcs
406 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
407 if internal_connection
["name"] in name_list
:
409 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
410 internal_connection
["name"]),
412 name_list
.append(internal_connection
["name"])
413 #We should check that internal-connections of type "ptp" have only 2 elements
415 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
417 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
418 internal_connection
["name"],
419 'ptp' if vnf_descriptor_version
==1 else 'e-line',
420 'data' if vnf_descriptor_version
==1 else "e-lan"),
422 for port
in internal_connection
["elements"]:
424 iface
= port
["local_iface_name"]
425 if vnf
not in vnfc_interfaces
:
427 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
428 internal_connection
["name"], vnf
),
430 if iface
not in vnfc_interfaces
[ vnf
]:
432 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
433 internal_connection
["name"], iface
),
435 return -HTTP_Bad_Request
,
436 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
437 if vnfc_interfaces
[vnf
][iface
] == "overlay":
438 internal_connection
["type"] = "bridge"
440 internal_connection
["type"] = "data"
441 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
442 if vnfc_interfaces
[vnf
][iface
] == "overlay":
443 internal_connection
["implementation"] = "overlay"
445 internal_connection
["implementation"] = "underlay"
446 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
447 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
449 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
450 internal_connection
["name"],
451 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
452 'data' if vnf_descriptor_version
==1 else 'underlay'),
454 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
455 vnfc_interfaces
[vnf
][iface
] == "underlay":
457 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
458 internal_connection
["name"], iface
,
459 'data' if vnf_descriptor_version
==1 else 'underlay',
460 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
464 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
466 if only_create_at_vim
:
467 image_mano_id
= image_dict
['uuid']
468 if return_on_error
== None:
469 return_on_error
= True
471 if image_dict
['location']:
472 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
474 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
476 image_mano_id
= images
[0]['uuid']
478 #create image in MANO DB
479 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
480 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
481 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
483 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
484 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
485 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
486 #create image at every vim
487 for vim_id
,vim
in vims
.iteritems():
488 image_created
="false"
490 image_db
= mydb
.get_rows(FROM
="datacenters_images", WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
491 #look at VIM if this image exist
493 if image_dict
['location'] is not None:
494 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
497 filter_dict
['name'] = image_dict
['universal_name']
498 if image_dict
.get('checksum') != None:
499 filter_dict
['checksum'] = image_dict
['checksum']
500 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
501 vim_images
= vim
.get_image_list(filter_dict
)
502 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
503 if len(vim_images
) > 1:
504 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), HTTP_Conflict
)
505 elif len(vim_images
) == 0:
506 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
508 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
509 image_vim_id
= vim_images
[0]['id']
511 except vimconn
.vimconnNotFoundException
as e
:
512 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
514 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
515 if image_dict
['location']:
516 image_vim_id
= vim
.new_image(image_dict
)
517 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
520 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
521 raise vimconn
.vimconnException(str(e
))
522 except vimconn
.vimconnException
as e
:
524 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
527 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
529 except vimconn
.vimconnException
as e
:
531 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
533 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
536 #if we reach here, the image has been created or existed
538 #add new vim_id at datacenters_images
539 mydb
.new_row('datacenters_images', {'datacenter_id':vim_id
, 'image_id':image_mano_id
, 'vim_id': image_vim_id
, 'created':image_created
})
540 elif image_db
[0]["vim_id"]!=image_vim_id
:
541 #modify existing vim_id at datacenters_images
542 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'image_id':image_mano_id
})
544 return image_vim_id
if only_create_at_vim
else image_mano_id
547 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
548 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
549 'ram':flavor_dict
.get('ram'),
550 'vcpus':flavor_dict
.get('vcpus'),
552 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
553 del flavor_dict
['extended']
554 if 'extended' in flavor_dict
:
555 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
557 #look if flavor exist
558 if only_create_at_vim
:
559 flavor_mano_id
= flavor_dict
['uuid']
560 if return_on_error
== None:
561 return_on_error
= True
563 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
565 flavor_mano_id
= flavors
[0]['uuid']
568 #create one by one the images of aditional disks
569 dev_image_list
=[] #list of images
570 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
572 for device
in flavor_dict
['extended'].get('devices',[]):
573 if "image" not in device
and "image name" not in device
:
576 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
577 image_dict
['universal_name']=device
.get('image name')
578 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
579 image_dict
['location']=device
.get('image')
580 #image_dict['new_location']=vnfc.get('image location')
581 image_dict
['checksum']=device
.get('image checksum')
582 image_metadata_dict
= device
.get('image metadata', None)
583 image_metadata_str
= None
584 if image_metadata_dict
!= None:
585 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
586 image_dict
['metadata']=image_metadata_str
587 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
588 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
589 dev_image_list
.append(image_id
)
591 temp_flavor_dict
['name'] = flavor_dict
['name']
592 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
593 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
594 flavor_mano_id
= content
595 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
596 #create flavor at every vim
597 if 'uuid' in flavor_dict
:
598 del flavor_dict
['uuid']
600 for vim_id
,vim
in vims
.items():
601 flavor_created
="false"
603 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors", WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
604 #look at VIM if this flavor exist SKIPPED
605 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
607 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
611 #Create the flavor in VIM
612 #Translate images at devices from MANO id to VIM id
614 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
615 #make a copy of original devices
618 for device
in flavor_dict
["extended"].get("devices",[]):
621 devices_original
.append(dev
)
622 if 'image' in device
:
624 if 'image metadata' in device
:
625 del device
['image metadata']
627 for index
in range(0,len(devices_original
)) :
628 device
=devices_original
[index
]
629 if "image" not in device
and "image name" not in device
:
631 disk_list
.append({'size': device
.get('size', default_volume_size
)})
634 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
635 image_dict
['universal_name']=device
.get('image name')
636 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
637 image_dict
['location']=device
.get('image')
638 #image_dict['new_location']=device.get('image location')
639 image_dict
['checksum']=device
.get('image checksum')
640 image_metadata_dict
= device
.get('image metadata', None)
641 image_metadata_str
= None
642 if image_metadata_dict
!= None:
643 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
644 image_dict
['metadata']=image_metadata_str
645 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
646 image_dict
["uuid"]=image_mano_id
647 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
649 #save disk information (image must be based on and size
650 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
652 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
655 #check that this vim_id exist in VIM, if not create
656 flavor_vim_id
=flavor_db
[0]["vim_id"]
658 vim
.get_flavor(flavor_vim_id
)
659 continue #flavor exist
660 except vimconn
.vimconnException
:
662 #create flavor at vim
663 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
666 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
667 flavor_create
="false"
668 except vimconn
.vimconnException
as e
:
671 if not flavor_vim_id
:
672 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
673 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
674 flavor_created
="true"
675 except vimconn
.vimconnException
as e
:
677 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
679 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
682 #if reach here the flavor has been create or exist
683 if len(flavor_db
)==0:
684 #add new vim_id at datacenters_flavors
685 extended_devices_yaml
= None
686 if len(disk_list
) > 0:
687 extended_devices
= dict()
688 extended_devices
['disks'] = disk_list
689 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
690 mydb
.new_row('datacenters_flavors',
691 {'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
, 'vim_id': flavor_vim_id
,
692 'created':flavor_created
,'extended': extended_devices_yaml
})
693 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
694 #modify existing vim_id at datacenters_flavors
695 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
}, WHERE
={'datacenter_id':vim_id
, 'flavor_id':flavor_mano_id
})
697 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
700 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
703 # Step 1. Check the VNF descriptor
704 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
705 # Step 2. Check tenant exist
707 if tenant_id
!= "any":
708 check_tenant(mydb
, tenant_id
)
709 if "tenant_id" in vnf_descriptor
["vnf"]:
710 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
711 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
714 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
715 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
716 if global_config
["auto_push_VNF_to_VIMs"]:
717 vims
= get_vim(mydb
, tenant_id
)
719 # Step 4. Review the descriptor and add missing fields
720 #print vnf_descriptor
721 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
722 vnf_name
= vnf_descriptor
['vnf']['name']
723 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
724 if "physical" in vnf_descriptor
['vnf']:
725 del vnf_descriptor
['vnf']['physical']
726 #print vnf_descriptor
728 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
729 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
730 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
732 #For each VNFC, we add it to the VNFCDict and we create a flavor.
733 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
734 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
736 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
737 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
739 VNFCitem
["name"] = vnfc
['name']
740 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
742 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
745 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
746 myflavorDict
["description"] = VNFCitem
["description"]
747 myflavorDict
["ram"] = vnfc
.get("ram", 0)
748 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
749 myflavorDict
["disk"] = vnfc
.get("disk", 1)
750 myflavorDict
["extended"] = {}
752 devices
= vnfc
.get("devices")
754 myflavorDict
["extended"]["devices"] = devices
757 # 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
758 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
760 # Previous code has been commented
761 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
762 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
763 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
764 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
766 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
768 # print "Error creating flavor: unknown processor model. Rollback successful."
769 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
771 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
772 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
774 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
775 myflavorDict
['extended']['numas'] = vnfc
['numas']
779 # Step 6.2 New flavors are created in the VIM
780 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
782 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
783 VNFCitem
["flavor_id"] = flavor_id
784 VNFCDict
[vnfc
['name']] = VNFCitem
786 logger
.debug("Creating new images in the VIM for each VNFC")
787 # Step 6.3 New images are created in the VIM
788 #For each VNFC, we must create the appropriate image.
789 #This "for" loop might be integrated with the previous one
790 #In case this integration is made, the VNFCDict might become a VNFClist.
791 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
792 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
794 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
795 image_dict
['universal_name']=vnfc
.get('image name')
796 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
797 image_dict
['location']=vnfc
.get('VNFC image')
798 #image_dict['new_location']=vnfc.get('image location')
799 image_dict
['checksum']=vnfc
.get('image checksum')
800 image_metadata_dict
= vnfc
.get('image metadata', None)
801 image_metadata_str
= None
802 if image_metadata_dict
is not None:
803 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
804 image_dict
['metadata']=image_metadata_str
805 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
806 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
807 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
808 VNFCDict
[vnfc
['name']]["image_id"] = image_id
809 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
810 if vnfc
.get("boot-data"):
811 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
814 # Step 7. Storing the VNF descriptor in the repository
815 if "descriptor" not in vnf_descriptor
["vnf"]:
816 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
818 # Step 8. Adding the VNF to the NFVO DB
819 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
821 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
822 _
, message
= rollback(mydb
, vims
, rollback_list
)
823 if isinstance(e
, db_base_Exception
):
824 error_text
= "Exception at database"
825 elif isinstance(e
, KeyError):
826 error_text
= "KeyError exception "
827 e
.http_code
= HTTP_Internal_Server_Error
829 error_text
= "Exception at VIM"
830 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
831 #logger.error("start_scenario %s", error_text)
832 raise NfvoException(error_text
, e
.http_code
)
835 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
838 # Step 1. Check the VNF descriptor
839 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
840 # Step 2. Check tenant exist
842 if tenant_id
!= "any":
843 check_tenant(mydb
, tenant_id
)
844 if "tenant_id" in vnf_descriptor
["vnf"]:
845 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
846 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
849 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
850 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
851 if global_config
["auto_push_VNF_to_VIMs"]:
852 vims
= get_vim(mydb
, tenant_id
)
854 # Step 4. Review the descriptor and add missing fields
855 #print vnf_descriptor
856 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
857 vnf_name
= vnf_descriptor
['vnf']['name']
858 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
859 if "physical" in vnf_descriptor
['vnf']:
860 del vnf_descriptor
['vnf']['physical']
861 #print vnf_descriptor
863 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
864 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
865 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
867 #For each VNFC, we add it to the VNFCDict and we create a flavor.
868 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
869 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
871 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
872 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
874 VNFCitem
["name"] = vnfc
['name']
875 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
877 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
880 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
881 myflavorDict
["description"] = VNFCitem
["description"]
882 myflavorDict
["ram"] = vnfc
.get("ram", 0)
883 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
884 myflavorDict
["disk"] = vnfc
.get("disk", 1)
885 myflavorDict
["extended"] = {}
887 devices
= vnfc
.get("devices")
889 myflavorDict
["extended"]["devices"] = devices
892 # 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
893 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
895 # Previous code has been commented
896 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
897 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
898 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
899 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
901 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
903 # print "Error creating flavor: unknown processor model. Rollback successful."
904 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
906 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
907 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
909 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
910 myflavorDict
['extended']['numas'] = vnfc
['numas']
914 # Step 6.2 New flavors are created in the VIM
915 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
917 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
918 VNFCitem
["flavor_id"] = flavor_id
919 VNFCDict
[vnfc
['name']] = VNFCitem
921 logger
.debug("Creating new images in the VIM for each VNFC")
922 # Step 6.3 New images are created in the VIM
923 #For each VNFC, we must create the appropriate image.
924 #This "for" loop might be integrated with the previous one
925 #In case this integration is made, the VNFCDict might become a VNFClist.
926 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
927 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
929 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
930 image_dict
['universal_name']=vnfc
.get('image name')
931 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
932 image_dict
['location']=vnfc
.get('VNFC image')
933 #image_dict['new_location']=vnfc.get('image location')
934 image_dict
['checksum']=vnfc
.get('image checksum')
935 image_metadata_dict
= vnfc
.get('image metadata', None)
936 image_metadata_str
= None
937 if image_metadata_dict
is not None:
938 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
939 image_dict
['metadata']=image_metadata_str
940 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
941 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
942 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
943 VNFCDict
[vnfc
['name']]["image_id"] = image_id
944 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
945 if vnfc
.get("boot-data"):
946 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
948 # Step 7. Storing the VNF descriptor in the repository
949 if "descriptor" not in vnf_descriptor
["vnf"]:
950 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
952 # Step 8. Adding the VNF to the NFVO DB
953 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
955 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
956 _
, message
= rollback(mydb
, vims
, rollback_list
)
957 if isinstance(e
, db_base_Exception
):
958 error_text
= "Exception at database"
959 elif isinstance(e
, KeyError):
960 error_text
= "KeyError exception "
961 e
.http_code
= HTTP_Internal_Server_Error
963 error_text
= "Exception at VIM"
964 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
965 #logger.error("start_scenario %s", error_text)
966 raise NfvoException(error_text
, e
.http_code
)
969 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
970 #check valid tenant_id
971 check_tenant(mydb
, tenant_id
)
974 if tenant_id
!= "any":
975 where_or
["tenant_id"] = tenant_id
976 where_or
["public"] = True
977 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
980 filter_keys
= ('uuid','name','description','public', "tenant_id", "created_at")
981 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
982 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
983 data
={'vnf' : filtered_content
}
985 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
986 SELECT
=('vms.uuid as uuid','vms.name as name', 'vms.description as description', 'boot_data'),
987 WHERE
={'vnfs.uuid': vnf_id
} )
989 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
990 # change boot_data into boot-data
992 if vm
.get("boot_data"):
993 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
996 data
['vnf']['VNFC'] = content
997 #TODO: GET all the information from a VNFC and include it in the output.
1000 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1001 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1002 WHERE
={'vnfs.uuid': vnf_id
} )
1003 data
['vnf']['nets'] = content
1005 #GET ip-profile for each net
1006 for net
in data
['vnf']['nets']:
1007 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1008 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1009 WHERE
={'net_id': net
["uuid"]} )
1010 if len(ipprofiles
)==1:
1011 net
["ip_profile"] = ipprofiles
[0]
1012 elif len(ipprofiles
)>1:
1013 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
1016 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1018 #GET External Interfaces
1019 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1020 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1021 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1022 WHERE
={'vnfs.uuid': vnf_id
},
1023 WHERE_NOT
={'interfaces.external_name': None} )
1025 data
['vnf']['external-connections'] = content
1030 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1031 # Check tenant exist
1032 if tenant_id
!= "any":
1033 check_tenant(mydb
, tenant_id
)
1034 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1035 vims
= get_vim(mydb
, tenant_id
)
1039 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1041 if tenant_id
!= "any":
1042 where_or
["tenant_id"] = tenant_id
1043 where_or
["public"] = True
1044 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1045 vnf_id
= vnf
["uuid"]
1047 # "Getting the list of flavors and tenants of the VNF"
1048 flavorList
= get_flavorlist(mydb
, vnf_id
)
1049 if len(flavorList
)==0:
1050 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1052 imageList
= get_imagelist(mydb
, vnf_id
)
1053 if len(imageList
)==0:
1054 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1056 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1058 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1061 for flavor
in flavorList
:
1062 #check if flavor is used by other vnf
1064 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1066 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1068 #flavor not used, must be deleted
1070 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
1071 for flavor_vim
in c
:
1072 if flavor_vim
["datacenter_id"] not in vims
:
1074 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
1076 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
1078 myvim
.delete_flavor(flavor_vim
["vim_id"])
1079 except vimconn
.vimconnNotFoundException
as e
:
1080 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
1081 except vimconn
.vimconnException
as e
:
1082 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1083 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1084 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
1085 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1086 mydb
.delete_row_by_id('flavors', flavor
)
1087 except db_base_Exception
as e
:
1088 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1089 undeletedItems
.append("flavor %s" % flavor
)
1092 for image
in imageList
:
1094 #check if image is used by other vnf
1095 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1097 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1099 #image not used, must be deleted
1101 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1103 if image_vim
["datacenter_id"] not in vims
:
1105 if image_vim
['created']=='false': #skip this image because not created by openmano
1107 myvim
=vims
[ image_vim
["datacenter_id"] ]
1109 myvim
.delete_image(image_vim
["vim_id"])
1110 except vimconn
.vimconnNotFoundException
as e
:
1111 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1112 except vimconn
.vimconnException
as e
:
1113 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1114 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1115 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1116 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1117 mydb
.delete_row_by_id('images', image
)
1118 except db_base_Exception
as e
:
1119 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1120 undeletedItems
.append("image %s" % image
)
1122 return vnf_id
+ " " + vnf
["name"]
1124 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1127 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1128 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1132 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1133 myvim
= vims
.values()[0]
1134 result
,servers
= myvim
.get_hosts_info()
1136 return result
, servers
1137 topology
= {'name':myvim
['name'] , 'servers': servers
}
1138 return result
, topology
1141 def get_hosts(mydb
, nfvo_tenant_id
):
1142 vims
= get_vim(mydb
, nfvo_tenant_id
)
1144 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1146 #print "nfvo.datacenter_action() error. Several datacenters found"
1147 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1148 myvim
= vims
.values()[0]
1150 hosts
= myvim
.get_hosts()
1151 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1153 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1155 server
={'name':host
['name'], 'vms':[]}
1156 for vm
in host
['instances']:
1157 #get internal name and model
1159 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1160 WHERE
={'vim_vm_id':vm
['id']} )
1162 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1164 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1166 except db_base_Exception
as e
:
1167 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1168 datacenter
['Datacenters'][0]['servers'].append(server
)
1169 #return -400, "en construccion"
1171 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1173 except vimconn
.vimconnException
as e
:
1174 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1177 def new_scenario(mydb
, tenant_id
, topo
):
1179 # result, vims = get_vim(mydb, tenant_id)
1181 # return result, vims
1183 if tenant_id
!= "any":
1184 check_tenant(mydb
, tenant_id
)
1185 if "tenant_id" in topo
:
1186 if topo
["tenant_id"] != tenant_id
:
1187 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1192 #1.1: get VNFs and external_networks (other_nets).
1194 other_nets
={} #external_networks, bridge_networks and data_networkds
1195 nodes
= topo
['topology']['nodes']
1196 for k
in nodes
.keys():
1197 if nodes
[k
]['type'] == 'VNF':
1199 vnfs
[k
]['ifaces'] = {}
1200 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1201 other_nets
[k
] = nodes
[k
]
1202 other_nets
[k
]['external']=True
1203 elif nodes
[k
]['type'] == 'network':
1204 other_nets
[k
] = nodes
[k
]
1205 other_nets
[k
]['external']=False
1208 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1209 for name
,vnf
in vnfs
.items():
1211 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1213 error_pos
= "'topology':'nodes':'" + name
+ "'"
1215 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1216 where
['uuid'] = vnf
['vnf_id']
1217 if 'VNF model' in vnf
:
1218 error_text
+= " 'VNF model' " + vnf
['VNF model']
1219 where
['name'] = vnf
['VNF model']
1221 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1223 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1229 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1231 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1232 vnf
['uuid']=vnf_db
[0]['uuid']
1233 vnf
['description']=vnf_db
[0]['description']
1234 #get external interfaces
1235 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1236 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1237 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1238 for ext_iface
in ext_ifaces
:
1239 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1241 #1.4 get list of connections
1242 conections
= topo
['topology']['connections']
1243 conections_list
= []
1244 conections_list_name
= []
1245 for k
in conections
.keys():
1246 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1247 ifaces_list
= conections
[k
]['nodes'].items()
1248 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1250 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1251 for k2
in conection_pair_list
:
1254 con_type
= conections
[k
].get("type", "link")
1255 if con_type
!= "link":
1257 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1258 other_nets
[k
] = {'external': False}
1259 if conections
[k
].get("graph"):
1260 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1261 ifaces_list
.append( (k
, None) )
1264 if con_type
== "external_network":
1265 other_nets
[k
]['external'] = True
1266 if conections
[k
].get("model"):
1267 other_nets
[k
]["model"] = conections
[k
]["model"]
1269 other_nets
[k
]["model"] = k
1270 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1271 other_nets
[k
]["model"] = con_type
1273 conections_list_name
.append(k
)
1274 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)
1275 #print set(ifaces_list)
1276 #check valid VNF and iface names
1277 for iface
in ifaces_list
:
1278 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1279 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1280 str(k
), iface
[0]), HTTP_Not_Found
)
1281 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1282 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1283 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1285 #1.5 unify connections from the pair list to a consolidated list
1287 while index
< len(conections_list
):
1289 while index2
< len(conections_list
):
1290 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1291 conections_list
[index
] |
= conections_list
[index2
]
1292 del conections_list
[index2
]
1293 del conections_list_name
[index2
]
1296 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1298 #for k in conections_list:
1303 #1.6 Delete non external nets
1304 # for k in other_nets.keys():
1305 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1306 # for con in conections_list:
1308 # for index in range(0,len(con)):
1309 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1310 # for index in delete_indexes:
1313 #1.7: Check external_ports are present at database table datacenter_nets
1314 for k
,net
in other_nets
.items():
1315 error_pos
= "'topology':'nodes':'" + k
+ "'"
1316 if net
['external']==False:
1317 if 'name' not in net
:
1319 if 'model' not in net
:
1320 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1321 if net
['model']=='bridge_net':
1322 net
['type']='bridge';
1323 elif net
['model']=='dataplane_net':
1326 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1328 #IF we do not want to check that external network exist at datacenter
1333 # if 'net_id' in net:
1334 # error_text += " 'net_id' " + net['net_id']
1335 # WHERE_['uuid'] = net['net_id']
1336 # if 'model' in net:
1337 # error_text += " 'model' " + net['model']
1338 # WHERE_['name'] = net['model']
1339 # if len(WHERE_) == 0:
1340 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1341 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1342 # FROM='datacenter_nets', WHERE=WHERE_ )
1344 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1346 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1347 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1349 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1350 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1351 # other_nets[k].update(net_db[0])
1354 net_nb
=0 #Number of nets
1355 for con
in conections_list
:
1356 #check if this is connected to a external net
1360 for index
in range(0,len(con
)):
1361 #check if this is connected to a external net
1362 for net_key
in other_nets
.keys():
1363 if con
[index
][0]==net_key
:
1364 if other_net_index
>=0:
1365 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1366 #print "nfvo.new_scenario " + error_text
1367 raise NfvoException(error_text
, HTTP_Bad_Request
)
1369 other_net_index
= index
1370 net_target
= net_key
1372 #print "other_net_index", other_net_index
1374 if other_net_index
>=0:
1375 del con
[other_net_index
]
1376 #IF we do not want to check that external network exist at datacenter
1377 if other_nets
[net_target
]['external'] :
1378 if "name" not in other_nets
[net_target
]:
1379 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1380 if other_nets
[net_target
]["type"] == "external_network":
1381 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1382 other_nets
[net_target
]["type"] = "data"
1384 other_nets
[net_target
]["type"] = "bridge"
1386 # if other_nets[net_target]['external'] :
1387 # 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
1388 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1389 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1390 # print "nfvo.new_scenario " + error_text
1391 # return -HTTP_Bad_Request, error_text
1394 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1397 net_type_bridge
=False
1399 net_target
= "__-__net"+str(net_nb
)
1400 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1401 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1404 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1405 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1406 if iface_type
=='mgmt' or iface_type
=='bridge':
1407 net_type_bridge
= True
1409 net_type_data
= True
1410 if net_type_bridge
and net_type_data
:
1411 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1412 #print "nfvo.new_scenario " + error_text
1413 raise NfvoException(error_text
, HTTP_Bad_Request
)
1414 elif net_type_bridge
:
1417 type_
='data' if len(con
)>2 else 'ptp'
1418 net_list
[net_target
]['type'] = type_
1421 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1422 #print "nfvo.new_scenario " + error_text
1424 raise NfvoException(error_text
, HTTP_Bad_Request
)
1426 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1427 #1.8.1 obtain management net
1428 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1429 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1430 #1.8.2 check all interfaces from all vnfs
1432 add_mgmt_net
= False
1433 for vnf
in vnfs
.values():
1434 for iface
in vnf
['ifaces'].values():
1435 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1436 #iface not connected
1437 iface
['net_key'] = 'mgmt'
1439 if add_mgmt_net
and 'mgmt' not in net_list
:
1440 net_list
['mgmt']=mgmt_net
[0]
1441 net_list
['mgmt']['external']=True
1442 net_list
['mgmt']['graph']={'visible':False}
1444 net_list
.update(other_nets
)
1446 #print 'net_list', net_list
1451 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1452 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1453 'tenant_id':tenant_id
, 'name':topo
['name'],
1454 'description':topo
.get('description',topo
['name']),
1455 'public': topo
.get('public', False)
1461 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
1462 """ This creates a new scenario for version 0.2 and 0.3"""
1463 scenario
= scenario_dict
["scenario"]
1464 if tenant_id
!= "any":
1465 check_tenant(mydb
, tenant_id
)
1466 if "tenant_id" in scenario
:
1467 if scenario
["tenant_id"] != tenant_id
:
1468 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1469 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1470 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1474 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
1475 for name
,vnf
in scenario
["vnfs"].iteritems():
1477 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1479 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1481 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1482 where
['uuid'] = vnf
['vnf_id']
1483 if 'vnf_name' in vnf
:
1484 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1485 where
['name'] = vnf
['vnf_name']
1487 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1488 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
1493 if len(vnf_db
) == 0:
1494 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1495 elif len(vnf_db
) > 1:
1496 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1497 vnf
['uuid'] = vnf_db
[0]['uuid']
1498 vnf
['description'] = vnf_db
[0]['description']
1500 # get external interfaces
1501 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
1502 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1503 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name': None} )
1504 for ext_iface
in ext_ifaces
:
1505 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
1506 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1508 # 2: Insert net_key and ip_address at every vnf interface
1509 for net_name
, net
in scenario
["networks"].items():
1510 net_type_bridge
= False
1511 net_type_data
= False
1512 for iface_dict
in net
["interfaces"]:
1513 if version
== "0.2":
1514 temp_dict
= iface_dict
1516 elif version
== "0.3":
1517 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
1518 ip_address
= iface_dict
.get('ip_address', None)
1519 for vnf
, iface
in temp_dict
.items():
1520 if vnf
not in scenario
["vnfs"]:
1521 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
1523 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1524 raise NfvoException(error_text
, HTTP_Not_Found
)
1525 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1526 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
1527 .format(net_name
, iface
)
1528 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1529 raise NfvoException(error_text
, HTTP_Bad_Request
)
1530 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1531 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
1532 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1533 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1534 raise NfvoException(error_text
, HTTP_Bad_Request
)
1535 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1536 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
1537 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1538 if iface_type
== 'mgmt' or iface_type
== 'bridge':
1539 net_type_bridge
= True
1541 net_type_data
= True
1543 if net_type_bridge
and net_type_data
:
1544 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
1546 # logger.debug("nfvo.new_scenario " + error_text)
1547 raise NfvoException(error_text
, HTTP_Bad_Request
)
1548 elif net_type_bridge
:
1551 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
1553 if net
.get("implementation"): # for v0.3
1554 if type_
== "bridge" and net
["implementation"] == "underlay":
1555 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
1556 "'network':'{}'".format(net_name
)
1557 # logger.debug(error_text)
1558 raise NfvoException(error_text
, HTTP_Bad_Request
)
1559 elif type_
!= "bridge" and net
["implementation"] == "overlay":
1560 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
1561 "'network':'{}'".format(net_name
)
1562 # logger.debug(error_text)
1563 raise NfvoException(error_text
, HTTP_Bad_Request
)
1564 net
.pop("implementation")
1565 if "type" in net
and version
== "0.3": # for v0.3
1566 if type_
== "data" and net
["type"] == "e-line":
1567 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
1568 "'e-line' at 'network':'{}'".format(net_name
)
1569 # logger.debug(error_text)
1570 raise NfvoException(error_text
, HTTP_Bad_Request
)
1571 elif type_
== "ptp" and net
["type"] == "e-lan":
1575 net
['name'] = net_name
1576 net
['external'] = net
.get('external', False)
1578 # 3: insert at database
1579 scenario
["nets"] = scenario
["networks"]
1580 scenario
['tenant_id'] = tenant_id
1581 scenario_id
= mydb
.new_scenario(scenario
)
1585 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
1586 data
["uuid"] = scenario_id
1587 data
["tenant_id"] = tenant_id
1588 c
= mydb
.edit_scenario( data
)
1592 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
1593 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1594 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
1595 vims
= {datacenter_id
: myvim
}
1596 myvim_tenant
= myvim
['tenant_id']
1597 datacenter_name
= myvim
['name']
1601 #print "Checking that the scenario_id exists and getting the scenario dictionary"
1602 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
)
1603 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
1604 scenarioDict
['datacenter_id'] = datacenter_id
1605 #print '================scenarioDict======================='
1606 #print json.dumps(scenarioDict, indent=4)
1607 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
1609 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
1610 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1612 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1613 auxNetDict
['scenario'] = {}
1615 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
1616 for sce_net
in scenarioDict
['nets']:
1617 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
1619 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
1620 myNetName
= myNetName
[0:255] #limit length
1621 myNetType
= sce_net
['type']
1623 myNetDict
["name"] = myNetName
1624 myNetDict
["type"] = myNetType
1625 myNetDict
["tenant_id"] = myvim_tenant
1626 myNetIPProfile
= sce_net
.get('ip_profile', None)
1628 #We should use the dictionary as input parameter for new_network
1630 if not sce_net
["external"]:
1631 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1632 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
1633 sce_net
['vim_id'] = network_id
1634 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
1635 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1636 sce_net
["created"] = True
1638 if sce_net
['vim_id'] == None:
1639 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
1640 _
, message
= rollback(mydb
, vims
, rollbackList
)
1641 logger
.error("nfvo.start_scenario: %s", error_text
)
1642 raise NfvoException(error_text
, HTTP_Bad_Request
)
1643 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
1644 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
1646 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
1647 #For each vnf net, we create it and we add it to instanceNetlist.
1648 for sce_vnf
in scenarioDict
['vnfs']:
1649 for net
in sce_vnf
['nets']:
1650 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
1652 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
1653 myNetName
= myNetName
[0:255] #limit length
1654 myNetType
= net
['type']
1656 myNetDict
["name"] = myNetName
1657 myNetDict
["type"] = myNetType
1658 myNetDict
["tenant_id"] = myvim_tenant
1659 myNetIPProfile
= net
.get('ip_profile', None)
1662 #We should use the dictionary as input parameter for new_network
1663 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
1664 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
1665 net
['vim_id'] = network_id
1666 if sce_vnf
['uuid'] not in auxNetDict
:
1667 auxNetDict
[sce_vnf
['uuid']] = {}
1668 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
1669 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
1670 net
["created"] = True
1672 #print "auxNetDict:"
1673 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
1675 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
1676 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
1678 for sce_vnf
in scenarioDict
['vnfs']:
1679 for vm
in sce_vnf
['vms']:
1682 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
1683 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
1684 #myVMDict['description'] = vm['description']
1685 myVMDict
['description'] = myVMDict
['name'][0:99]
1687 myVMDict
['start'] = "no"
1688 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
1689 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
1691 #create image at vim in case it not exist
1692 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
1693 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
1694 vm
['vim_image_id'] = image_id
1696 #create flavor at vim in case it not exist
1697 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
1698 if flavor_dict
['extended']!=None:
1699 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
1700 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
1701 vm
['vim_flavor_id'] = flavor_id
1704 myVMDict
['imageRef'] = vm
['vim_image_id']
1705 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
1706 myVMDict
['networks'] = []
1707 for iface
in vm
['interfaces']:
1709 if iface
['type']=="data":
1710 netDict
['type'] = iface
['model']
1711 elif "model" in iface
and iface
["model"]!=None:
1712 netDict
['model']=iface
['model']
1713 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
1714 #discover type of interface looking at flavor
1715 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
1716 for flavor_iface
in numa
.get('interfaces',[]):
1717 if flavor_iface
.get('name') == iface
['internal_name']:
1718 if flavor_iface
['dedicated'] == 'yes':
1719 netDict
['type']="PF" #passthrough
1720 elif flavor_iface
['dedicated'] == 'no':
1721 netDict
['type']="VF" #siov
1722 elif flavor_iface
['dedicated'] == 'yes:sriov':
1723 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
1724 netDict
["mac_address"] = flavor_iface
.get("mac_address")
1726 netDict
["use"]=iface
['type']
1727 if netDict
["use"]=="data" and not netDict
.get("type"):
1728 #print "netDict", netDict
1729 #print "iface", iface
1730 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'])
1731 if flavor_dict
.get('extended')==None:
1732 raise NfvoException(e_text
+ "After database migration some information is not available. \
1733 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
1735 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
1736 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
1737 netDict
["type"]="virtual"
1738 if "vpci" in iface
and iface
["vpci"] is not None:
1739 netDict
['vpci'] = iface
['vpci']
1740 if "mac" in iface
and iface
["mac"] is not None:
1741 netDict
['mac_address'] = iface
['mac']
1742 if "port-security" in iface
and iface
["port-security"] is not None:
1743 netDict
['port_security'] = iface
['port-security']
1744 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
1745 netDict
['floating_ip'] = iface
['floating-ip']
1746 netDict
['name'] = iface
['internal_name']
1747 if iface
['net_id'] is None:
1748 for vnf_iface
in sce_vnf
["interfaces"]:
1751 if vnf_iface
['interface_id']==iface
['uuid']:
1752 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
1755 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
1756 #skip bridge ifaces not connected to any net
1757 #if 'net_id' not in netDict or netDict['net_id']==None:
1759 myVMDict
['networks'].append(netDict
)
1760 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1761 #print myVMDict['name']
1762 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
1763 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
1764 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
1765 vm_id
= myvim
.new_vminstance(myVMDict
['name'],myVMDict
['description'],myVMDict
.get('start', None),
1766 myVMDict
['imageRef'],myVMDict
['flavorRef'],myVMDict
['networks'])
1767 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
1768 vm
['vim_id'] = vm_id
1769 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
1770 #put interface uuid back to scenario[vnfs][vms[[interfaces]
1771 for net
in myVMDict
['networks']:
1773 for iface
in vm
['interfaces']:
1774 if net
["name"]==iface
["internal_name"]:
1775 iface
["vim_id"]=net
["vim_id"]
1778 logger
.debug("start scenario Deployment done")
1779 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
1780 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
1781 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
1782 return mydb
.get_instance_scenario(instance_id
)
1784 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
1785 _
, message
= rollback(mydb
, vims
, rollbackList
)
1786 if isinstance(e
, db_base_Exception
):
1787 error_text
= "Exception at database"
1789 error_text
= "Exception at VIM"
1790 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1791 #logger.error("start_scenario %s", error_text)
1792 raise NfvoException(error_text
, e
.http_code
)
1795 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
1796 ''' join the cloud config information into cloud_config_preserve.
1797 In case of conflict cloud_config_preserve preserves
1800 if not cloud_config_preserve
and not cloud_config
:
1803 new_cloud_config
= {"key-pairs":[], "users":[]}
1805 if cloud_config_preserve
:
1806 for key
in cloud_config_preserve
.get("key-pairs", () ):
1807 if key
not in new_cloud_config
["key-pairs"]:
1808 new_cloud_config
["key-pairs"].append(key
)
1810 for key
in cloud_config
.get("key-pairs", () ):
1811 if key
not in new_cloud_config
["key-pairs"]:
1812 new_cloud_config
["key-pairs"].append(key
)
1813 if not new_cloud_config
["key-pairs"]:
1814 del new_cloud_config
["key-pairs"]
1818 new_cloud_config
["users"] += cloud_config
.get("users", () )
1819 if cloud_config_preserve
:
1820 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
1821 index_to_delete
= []
1822 users
= new_cloud_config
.get("users", [])
1823 for index0
in range(0,len(users
)):
1824 if index0
in index_to_delete
:
1826 for index1
in range(index0
+1,len(users
)):
1827 if index1
in index_to_delete
:
1829 if users
[index0
]["name"] == users
[index1
]["name"]:
1830 index_to_delete
.append(index1
)
1831 for key
in users
[index1
].get("key-pairs",()):
1832 if "key-pairs" not in users
[index0
]:
1833 users
[index0
]["key-pairs"] = [key
]
1834 elif key
not in users
[index0
]["key-pairs"]:
1835 users
[index0
]["key-pairs"].append(key
)
1836 index_to_delete
.sort(reverse
=True)
1837 for index
in index_to_delete
:
1839 if not new_cloud_config
["users"]:
1840 del new_cloud_config
["users"]
1843 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
1844 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
1845 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
1846 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
1849 if cloud_config
and cloud_config
.get("user-data") != None:
1850 new_cloud_config
["user-data"] = cloud_config
["user-data"]
1851 if cloud_config_preserve
and cloud_config_preserve
.get("user-data") != None:
1852 new_cloud_config
["user-data"] = cloud_config_preserve
["user-data"]
1855 new_cloud_config
["config-files"] = []
1856 if cloud_config
and cloud_config
.get("config-files") != None:
1857 new_cloud_config
["config-files"] += cloud_config
["config-files"]
1858 if cloud_config_preserve
:
1859 for file in cloud_config_preserve
.get("config-files", ()):
1860 for index
in range(0, len(new_cloud_config
["config-files"])):
1861 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
1862 new_cloud_config
["config-files"][index
] = file
1865 new_cloud_config
["config-files"].append(file)
1866 if not new_cloud_config
["config-files"]:
1867 del new_cloud_config
["config-files"]
1868 return new_cloud_config
1871 def get_vim_thread(tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
1872 datacenter_id
= None
1873 datacenter_name
= None
1875 if datacenter_id_name
:
1876 if utils
.check_valid_uuid(datacenter_id_name
):
1877 datacenter_id
= datacenter_id_name
1879 datacenter_name
= datacenter_id_name
1881 thread
= vim_threads
["running"].get(datacenter_id
+ "." + tenant_id
)
1883 for k
, v
in vim_threads
["running"].items():
1884 datacenter_tenant
= k
.split(".")
1885 if datacenter_tenant
[0] == datacenter_id
and datacenter_tenant
[1] == tenant_id
:
1887 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1889 elif not datacenter_id
and datacenter_tenant
[1] == tenant_id
:
1890 if thread
.datacenter_name
== datacenter_name
:
1892 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1895 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1899 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
1900 datacenter_id
= None
1901 datacenter_name
= None
1902 if datacenter_id_name
:
1903 if utils
.check_valid_uuid(datacenter_id_name
):
1904 datacenter_id
= datacenter_id_name
1906 datacenter_name
= datacenter_id_name
1907 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
1909 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
1911 #print "nfvo.datacenter_action() error. Several datacenters found"
1912 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1913 return vims
.keys()[0], vims
.values()[0]
1917 '''Takes dict d and updates it with the values in dict u.'''
1918 '''It merges all depth levels'''
1919 for k
, v
in u
.iteritems():
1920 if isinstance(v
, collections
.Mapping
):
1921 r
= update(d
.get(k
, {}), v
)
1928 def create_instance(mydb
, tenant_id
, instance_dict
):
1929 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
1930 # logger.debug("Creating instance...")
1931 scenario
= instance_dict
["scenario"]
1933 #find main datacenter
1936 datacenter2tenant
= {}
1937 datacenter
= instance_dict
.get("datacenter")
1938 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
1939 myvims
[default_datacenter_id
] = vim
1940 myvim_threads
[default_datacenter_id
] = get_vim_thread(tenant_id
, default_datacenter_id
)
1941 datacenter2tenant
[default_datacenter_id
] = vim
['config']['datacenter_tenant_id']
1942 #myvim_tenant = myvim['tenant_id']
1943 # default_datacenter_name = vim['name']
1946 #print "Checking that the scenario exists and getting the scenario dictionary"
1947 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, default_datacenter_id
)
1949 #logger.debug(">>>>>>> Dictionaries before merging")
1950 #logger.debug(">>>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
1951 #logger.debug(">>>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
1953 scenarioDict
['datacenter_id'] = default_datacenter_id
1955 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
1956 auxNetDict
['scenario'] = {}
1958 logger
.debug("Creating instance from scenario-dict:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False)) #TODO remove
1959 instance_name
= instance_dict
["name"]
1960 instance_description
= instance_dict
.get("description")
1963 # 0 check correct parameters
1964 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
1966 for scenario_net
in scenarioDict
['nets']:
1967 if net_name
== scenario_net
["name"]:
1971 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
), HTTP_Bad_Request
)
1972 if "sites" not in net_instance_desc
:
1973 net_instance_desc
["sites"] = [ {} ]
1974 site_without_datacenter_field
= False
1975 for site
in net_instance_desc
["sites"]:
1976 if site
.get("datacenter"):
1977 if site
["datacenter"] not in myvims
:
1978 #Add this datacenter to myvims
1979 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
1981 myvim_threads
[d
] = get_vim_thread(tenant_id
, site
["datacenter"])
1982 datacenter2tenant
[d
] = v
['config']['datacenter_tenant_id']
1983 site
["datacenter"] = d
#change name to id
1985 if site_without_datacenter_field
:
1986 raise NfvoException("Found more than one entries without datacenter field at instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
1987 site_without_datacenter_field
= True
1988 site
["datacenter"] = default_datacenter_id
#change name to id
1990 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
1992 for scenario_vnf
in scenarioDict
['vnfs']:
1993 if vnf_name
== scenario_vnf
['name']:
1997 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
1998 if "datacenter" in vnf_instance_desc
:
1999 # Add this datacenter to myvims
2000 if vnf_instance_desc
["datacenter"] not in myvims
:
2001 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2003 myvim_threads
[d
] = get_vim_thread(tenant_id
, vnf_instance_desc
["datacenter"])
2004 datacenter2tenant
[d
] = v
['config']['datacenter_tenant_id']
2005 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2007 #0.1 parse cloud-config parameters
2008 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2010 #0.2 merge instance information into scenario
2011 #Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2012 #However, this is not possible yet.
2013 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2014 for scenario_net
in scenarioDict
['nets']:
2015 if net_name
== scenario_net
["name"]:
2016 if 'ip-profile' in net_instance_desc
:
2017 ipprofile
= net_instance_desc
['ip-profile']
2018 ipprofile
['subnet_address'] = ipprofile
.pop('subnet-address',None)
2019 ipprofile
['ip_version'] = ipprofile
.pop('ip-version','IPv4')
2020 ipprofile
['gateway_address'] = ipprofile
.pop('gateway-address',None)
2021 ipprofile
['dns_address'] = ipprofile
.pop('dns-address',None)
2022 if 'dhcp' in ipprofile
:
2023 ipprofile
['dhcp_start_address'] = ipprofile
['dhcp'].get('start-address',None)
2024 ipprofile
['dhcp_enabled'] = ipprofile
['dhcp'].get('enabled',True)
2025 ipprofile
['dhcp_count'] = ipprofile
['dhcp'].get('count',None)
2026 del ipprofile
['dhcp']
2027 if 'ip_profile' not in scenario_net
:
2028 scenario_net
['ip_profile'] = ipprofile
2030 update(scenario_net
['ip_profile'],ipprofile
)
2031 for interface
in net_instance_desc
.get('interfaces', () ):
2032 if 'ip_address' in interface
:
2033 for vnf
in scenarioDict
['vnfs']:
2034 if interface
['vnf'] == vnf
['name']:
2035 for vnf_interface
in vnf
['interfaces']:
2036 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2037 vnf_interface
['ip_address']=interface
['ip_address']
2039 #logger.debug(">>>>>>>> Merged dictionary")
2040 logger
.debug("Creating instance scenario-dict MERGED:\n%s", yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False))
2043 # 1. Creating new nets (sce_nets) in the VIM"
2044 for sce_net
in scenarioDict
['nets']:
2045 sce_net
["vim_id_sites"]={}
2046 descriptor_net
= instance_dict
.get("networks",{}).get(sce_net
["name"],{})
2047 net_name
= descriptor_net
.get("vim-network-name")
2048 auxNetDict
['scenario'][sce_net
['uuid']] = {}
2050 sites
= descriptor_net
.get("sites", [ {} ])
2052 if site
.get("datacenter"):
2053 vim
= myvims
[ site
["datacenter"] ]
2054 datacenter_id
= site
["datacenter"]
2055 myvim_thread
= myvim_threads
[ site
["datacenter"] ]
2057 vim
= myvims
[ default_datacenter_id
]
2058 datacenter_id
= default_datacenter_id
2059 myvim_thread
= myvim_threads
[default_datacenter_id
]
2060 net_type
= sce_net
['type']
2061 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} #'shared': True
2062 if sce_net
["external"]:
2064 net_name
= sce_net
["name"]
2065 if "netmap-use" in site
or "netmap-create" in site
:
2066 create_network
= False
2067 lookfor_network
= False
2068 if "netmap-use" in site
:
2069 lookfor_network
= True
2070 if utils
.check_valid_uuid(site
["netmap-use"]):
2071 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2072 lookfor_filter
["id"] = site
["netmap-use"]
2074 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2075 lookfor_filter
["name"] = site
["netmap-use"]
2076 if "netmap-create" in site
:
2077 create_network
= True
2078 net_vim_name
= net_name
2079 if site
["netmap-create"]:
2080 net_vim_name
= site
["netmap-create"]
2082 elif sce_net
['vim_id'] != None:
2083 #there is a netmap at datacenter_nets database #TODO REVISE!!!!
2084 create_network
= False
2085 lookfor_network
= True
2086 lookfor_filter
["id"] = sce_net
['vim_id']
2087 filter_text
= "vim_id '%s' datacenter_netmap name '%s'. Try to reload vims with datacenter-net-update" % (sce_net
['vim_id'], sce_net
["name"])
2088 #look for network at datacenter and return error
2090 #There is not a netmap, look at datacenter for a net with this name and create if not found
2091 create_network
= True
2092 lookfor_network
= True
2093 lookfor_filter
["name"] = sce_net
["name"]
2094 net_vim_name
= sce_net
["name"]
2095 filter_text
= "scenario name '%s'" % sce_net
["name"]
2098 net_name
= "%s.%s" %(instance_name
, sce_net
["name"])
2099 net_name
= net_name
[:255] #limit length
2100 net_vim_name
= net_name
2101 create_network
= True
2102 lookfor_network
= False
2105 vim_nets
= vim
.get_network_list(filter_dict
=lookfor_filter
)
2106 if len(vim_nets
) > 1:
2107 raise NfvoException("More than one candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2108 elif len(vim_nets
) == 0:
2109 if not create_network
:
2110 raise NfvoException("No candidate VIM network found for " + filter_text
, HTTP_Bad_Request
)
2112 sce_net
["vim_id_sites"][datacenter_id
] = vim_nets
[0]['id']
2113 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = vim_nets
[0]['id']
2114 create_network
= False
2116 #if network is not external
2117 task
= new_task("new-net", (net_vim_name
, net_type
, sce_net
.get('ip_profile',None)))
2118 task_id
= myvim_thread
.insert_task(task
)
2119 instance_tasks
[task_id
] = task
2120 #network_id = vim.new_network(net_vim_name, net_type, sce_net.get('ip_profile',None))
2121 sce_net
["vim_id_sites"][datacenter_id
] = task_id
2122 auxNetDict
['scenario'][sce_net
['uuid']][datacenter_id
] = task_id
2123 rollbackList
.append({'what':'network', 'where':'vim', 'vim_id':datacenter_id
, 'uuid':task_id
})
2124 sce_net
["created"] = True
2126 # 2. Creating new nets (vnf internal nets) in the VIM"
2127 #For each vnf net, we create it and we add it to instanceNetlist.
2128 for sce_vnf
in scenarioDict
['vnfs']:
2129 for net
in sce_vnf
['nets']:
2130 if sce_vnf
.get("datacenter"):
2131 vim
= myvims
[ sce_vnf
["datacenter"] ]
2132 datacenter_id
= sce_vnf
["datacenter"]
2133 myvim_thread
= myvim_threads
[ sce_vnf
["datacenter"]]
2135 vim
= myvims
[ default_datacenter_id
]
2136 datacenter_id
= default_datacenter_id
2137 myvim_thread
= myvim_threads
[default_datacenter_id
]
2138 descriptor_net
= instance_dict
.get("vnfs",{}).get(sce_vnf
["name"],{})
2139 net_name
= descriptor_net
.get("name")
2141 net_name
= "%s.%s" %(instance_name
, net
["name"])
2142 net_name
= net_name
[:255] #limit length
2143 net_type
= net
['type']
2144 task
= new_task("new-net", (net_name
, net_type
, net
.get('ip_profile',None)))
2145 task_id
= myvim_thread
.insert_task(task
)
2146 instance_tasks
[task_id
] = task
2147 # network_id = vim.new_network(net_name, net_type, net.get('ip_profile',None))
2148 net
['vim_id'] = task_id
2149 if sce_vnf
['uuid'] not in auxNetDict
:
2150 auxNetDict
[sce_vnf
['uuid']] = {}
2151 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = task_id
2152 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':task_id
})
2153 net
["created"] = True
2156 #print "auxNetDict:"
2157 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2159 # 3. Creating new vm instances in the VIM
2160 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2161 for sce_vnf
in scenarioDict
['vnfs']:
2162 if sce_vnf
.get("datacenter"):
2163 vim
= myvims
[ sce_vnf
["datacenter"] ]
2164 myvim_thread
= myvim_threads
[ sce_vnf
["datacenter"] ]
2165 datacenter_id
= sce_vnf
["datacenter"]
2167 vim
= myvims
[ default_datacenter_id
]
2168 myvim_thread
= myvim_threads
[ default_datacenter_id
]
2169 datacenter_id
= default_datacenter_id
2170 sce_vnf
["datacenter_id"] = datacenter_id
2172 for vm
in sce_vnf
['vms']:
2175 myVMDict
['name'] = "{}.{}.{}".format(instance_name
,sce_vnf
['name'],chr(96+i
))
2176 myVMDict
['description'] = myVMDict
['name'][0:99]
2178 # myVMDict['start'] = "no"
2179 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2180 #create image at vim in case it not exist
2181 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2182 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2183 vm
['vim_image_id'] = image_id
2185 #create flavor at vim in case it not exist
2186 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2187 if flavor_dict
['extended']!=None:
2188 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2189 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
2191 #Obtain information for additional disks
2192 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
2193 if not extended_flavor_dict
:
2194 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
2197 #extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
2198 myVMDict
['disks'] = None
2199 extended_info
= extended_flavor_dict
[0]['extended']
2200 if extended_info
!= None:
2201 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
2202 if 'disks' in extended_flavor_dict_yaml
:
2203 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
2205 vm
['vim_flavor_id'] = flavor_id
2206 myVMDict
['imageRef'] = vm
['vim_image_id']
2207 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2208 myVMDict
['networks'] = []
2210 #TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
2211 for iface
in vm
['interfaces']:
2213 if iface
['type']=="data":
2214 netDict
['type'] = iface
['model']
2215 elif "model" in iface
and iface
["model"]!=None:
2216 netDict
['model']=iface
['model']
2217 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2218 #discover type of interface looking at flavor
2219 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2220 for flavor_iface
in numa
.get('interfaces',[]):
2221 if flavor_iface
.get('name') == iface
['internal_name']:
2222 if flavor_iface
['dedicated'] == 'yes':
2223 netDict
['type']="PF" #passthrough
2224 elif flavor_iface
['dedicated'] == 'no':
2225 netDict
['type']="VF" #siov
2226 elif flavor_iface
['dedicated'] == 'yes:sriov':
2227 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2228 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2230 netDict
["use"]=iface
['type']
2231 if netDict
["use"]=="data" and not netDict
.get("type"):
2232 #print "netDict", netDict
2233 #print "iface", iface
2234 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'])
2235 if flavor_dict
.get('extended')==None:
2236 raise NfvoException(e_text
+ "After database migration some information is not available. \
2237 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2239 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2240 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2241 netDict
["type"]="virtual"
2242 if "vpci" in iface
and iface
["vpci"] is not None:
2243 netDict
['vpci'] = iface
['vpci']
2244 if "mac" in iface
and iface
["mac"] is not None:
2245 netDict
['mac_address'] = iface
['mac']
2246 if "port-security" in iface
and iface
["port-security"] is not None:
2247 netDict
['port_security'] = iface
['port-security']
2248 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2249 netDict
['floating_ip'] = iface
['floating-ip']
2250 netDict
['name'] = iface
['internal_name']
2251 if iface
['net_id'] is None:
2252 for vnf_iface
in sce_vnf
["interfaces"]:
2255 if vnf_iface
['interface_id']==iface
['uuid']:
2256 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
]
2259 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2260 if is_task_id(netDict
['net_id']):
2261 task_depends
[netDict
['net_id']] = instance_tasks
[netDict
['net_id']]
2262 #skip bridge ifaces not connected to any net
2263 #if 'net_id' not in netDict or netDict['net_id']==None:
2265 myVMDict
['networks'].append(netDict
)
2266 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2267 #print myVMDict['name']
2268 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2269 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2270 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2271 if vm
.get("boot_data"):
2272 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
2274 cloud_config_vm
= cloud_config
2275 task
= new_task("new-vm", (myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2276 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2277 cloud_config_vm
, myVMDict
['disks']), depends
=task_depends
)
2278 vm_id
= myvim_thread
.insert_task(task
)
2279 instance_tasks
[vm_id
] = task
2281 vm
['vim_id'] = vm_id
2282 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2283 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2284 for net
in myVMDict
['networks']:
2286 for iface
in vm
['interfaces']:
2287 if net
["name"]==iface
["internal_name"]:
2288 iface
["vim_id"]=net
["vim_id"]
2290 scenarioDict
["datacenter2tenant"] = datacenter2tenant
2291 logger
.debug("create_instance Deployment done scenarioDict: %s",
2292 yaml
.safe_dump(scenarioDict
, indent
=4, default_flow_style
=False) )
2293 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_name
, instance_description
, scenarioDict
)
2294 # Update database with those ended tasks
2295 for task
in instance_tasks
.values():
2296 if task
["status"] == "ok":
2297 if task
["name"] == "new-vm":
2298 mydb
.update_rows("instance_vms", UPDATE
={"vim_vm_id": task
["result"]},
2299 WHERE
={"vim_vm_id": task
["id"]})
2300 elif task
["name"] == "new-net":
2301 mydb
.update_rows("instance_nets", UPDATE
={"vim_net_id": task
["result"]},
2302 WHERE
={"vim_net_id": task
["id"]})
2303 return mydb
.get_instance_scenario(instance_id
)
2304 except (NfvoException
, vimconn
.vimconnException
,db_base_Exception
) as e
:
2305 message
= rollback(mydb
, myvims
, rollbackList
)
2306 if isinstance(e
, db_base_Exception
):
2307 error_text
= "database Exception"
2308 elif isinstance(e
, vimconn
.vimconnException
):
2309 error_text
= "VIM Exception"
2311 error_text
= "Exception"
2312 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2313 #logger.error("create_instance: %s", error_text)
2314 raise NfvoException(error_text
, e
.http_code
)
2317 def delete_instance(mydb
, tenant_id
, instance_id
):
2318 #print "Checking that the instance_id exists and getting the instance dictionary"
2319 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
2320 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2321 tenant_id
= instanceDict
["tenant_id"]
2322 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2324 #1. Delete from Database
2325 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
2334 for sce_vnf
in instanceDict
['vnfs']:
2335 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2336 if datacenter_key
not in myvims
:
2338 myvim_thread
= get_vim_thread(tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2339 except NfvoException
as e
:
2340 logger
.error(str(e
))
2342 myvim_threads
[datacenter_key
] = myvim_thread
2343 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
2344 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2346 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
2347 sce_vnf
["datacenter_tenant_id"]))
2348 myvims
[datacenter_key
] = None
2350 myvims
[datacenter_key
] = vims
.values()[0]
2351 myvim
= myvims
[datacenter_key
]
2352 myvim_thread
= myvim_threads
[datacenter_key
]
2353 for vm
in sce_vnf
['vms']:
2355 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2359 if is_task_id(vm
['vim_vm_id']):
2360 task_id
= vm
['vim_vm_id']
2361 old_task
= task_dict
.get(task_id
)
2363 error_msg
+= "\n VM was scheduled for create, but task {} is not found".format(task_id
)
2366 if old_task
["status"] == "enqueued":
2367 old_task
["status"] = "deleted"
2368 elif old_task
["status"] == "error":
2370 elif old_task
["status"] == "processing":
2371 task
= new_task("del-vm", task_id
, depends
={task_id
: old_task
})
2373 task
= new_task("del-vm", old_task
["result"])
2375 task
= new_task("del-vm", vm
['vim_vm_id'], store
=False)
2377 myvim_thread
.insert_task(task
)
2378 except vimconn
.vimconnNotFoundException
as e
:
2379 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
2380 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
2381 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
2382 except vimconn
.vimconnException
as e
:
2383 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
2384 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
2385 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
2389 for net
in instanceDict
['nets']:
2390 if not net
['created']:
2391 continue #skip not created nets
2392 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2393 if datacenter_key
not in myvims
:
2395 myvim_thread
= get_vim_thread(tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2396 except NfvoException
as e
:
2397 logger
.error(str(e
))
2399 myvim_threads
[datacenter_key
] = myvim_thread
2400 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
2401 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2403 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2404 myvims
[datacenter_key
] = None
2406 myvims
[datacenter_key
] = vims
.values()[0]
2407 myvim
= myvims
[datacenter_key
]
2408 myvim_thread
= myvim_threads
[datacenter_key
]
2411 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
2415 if is_task_id(net
['vim_net_id']):
2416 task_id
= net
['vim_net_id']
2417 old_task
= task_dict
.get(task_id
)
2419 error_msg
+= "\n NET was scheduled for create, but task {} is not found".format(task_id
)
2422 if old_task
["status"] == "enqueued":
2423 old_task
["status"] = "deleted"
2424 elif old_task
["status"] == "error":
2426 elif old_task
["status"] == "processing":
2427 task
= new_task("del-net", task_id
, depends
={task_id
: old_task
})
2429 task
= new_task("del-net", old_task
["result"])
2431 task
= new_task("del-net", (net
['vim_net_id'], net
['sdn_net_id']), store
=False)
2433 myvim_thread
.insert_task(task
)
2434 except vimconn
.vimconnNotFoundException
as e
:
2435 error_msg
+= "\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
2436 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
2437 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
2438 except vimconn
.vimconnException
as e
:
2439 error_msg
+= "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'],
2440 net
["datacenter_id"],
2441 e
.http_code
, str(e
))
2442 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
2443 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
2444 if len(error_msg
) > 0:
2445 return 'instance ' + message
+ ' deleted but some elements could not be deleted, or already deleted (error: 404) from VIM: ' + error_msg
2447 return 'instance ' + message
+ ' deleted'
2450 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
2451 '''Refreshes a scenario instance. It modifies instanceDict'''
2453 - 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
2456 # Assumption: nfvo_tenant and instance_id were checked before entering into this function
2457 #print "nfvo.refresh_instance begins"
2458 #print json.dumps(instanceDict, indent=4)
2460 #print "Getting the VIM URL and the VIM tenant_id"
2463 # 1. Getting VIM vm and net list
2464 vms_updated
= [] #List of VM instance uuids in openmano that were updated
2467 for sce_vnf
in instanceDict
['vnfs']:
2468 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
2469 if datacenter_key
not in vm_list
:
2470 vm_list
[datacenter_key
] = []
2471 if datacenter_key
not in myvims
:
2472 vims
= get_vim(mydb
, nfvo_tenant
, datacenter_id
=sce_vnf
["datacenter_id"],
2473 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
2475 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"]))
2476 myvims
[datacenter_key
] = None
2478 myvims
[datacenter_key
] = vims
.values()[0]
2479 for vm
in sce_vnf
['vms']:
2480 vm_list
[datacenter_key
].append(vm
['vim_vm_id'])
2481 vms_notupdated
.append(vm
["uuid"])
2483 nets_updated
= [] #List of VM instance uuids in openmano that were updated
2486 for net
in instanceDict
['nets']:
2487 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
2488 if datacenter_key
not in net_list
:
2489 net_list
[datacenter_key
] = []
2490 if datacenter_key
not in myvims
:
2491 vims
= get_vim(mydb
, nfvo_tenant
, datacenter_id
=net
["datacenter_id"],
2492 datacenter_tenant_id
=net
["datacenter_tenant_id"])
2494 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
2495 myvims
[datacenter_key
] = None
2497 myvims
[datacenter_key
] = vims
.values()[0]
2499 net_list
[datacenter_key
].append(net
['vim_net_id'])
2500 nets_notupdated
.append(net
["uuid"])
2502 # 1. Getting the status of all VMs
2504 for datacenter_key
in myvims
:
2505 if not vm_list
.get(datacenter_key
):
2509 if not myvims
[datacenter_key
]:
2510 failed_message
= "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"])
2513 vm_dict
.update(myvims
[datacenter_key
].refresh_vms_status(vm_list
[datacenter_key
]) )
2515 except vimconn
.vimconnException
as e
:
2516 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
2517 failed_message
= str(e
)
2519 for vm
in vm_list
[datacenter_key
]:
2520 vm_dict
[vm
] = {'status': "VIM_ERROR", 'error_msg': failed_message
}
2522 # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
2523 for sce_vnf
in instanceDict
['vnfs']:
2524 for vm
in sce_vnf
['vms']:
2525 vm_id
= vm
['vim_vm_id']
2526 interfaces
= vm_dict
[vm_id
].pop('interfaces', [])
2527 #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
2528 has_mgmt_iface
= False
2529 for iface
in vm
["interfaces"]:
2530 if iface
["type"]=="mgmt":
2531 has_mgmt_iface
= True
2532 if vm_dict
[vm_id
]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface
:
2533 vm_dict
[vm_id
]['status'] = "ACTIVE"
2534 if vm_dict
[vm_id
].get('error_msg') and len(vm_dict
[vm_id
]['error_msg']) >= 1024:
2535 vm_dict
[vm_id
]['error_msg'] = vm_dict
[vm_id
]['error_msg'][:516] + " ... " + vm_dict
[vm_id
]['error_msg'][-500:]
2536 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'):
2537 vm
['status'] = vm_dict
[vm_id
]['status']
2538 vm
['error_msg'] = vm_dict
[vm_id
].get('error_msg')
2539 vm
['vim_info'] = vm_dict
[vm_id
].get('vim_info')
2540 # 2.1. Update in openmano DB the VMs whose status changed
2542 updates
= mydb
.update_rows('instance_vms', UPDATE
=vm_dict
[vm_id
], WHERE
={'uuid':vm
["uuid"]})
2543 vms_notupdated
.remove(vm
["uuid"])
2545 vms_updated
.append(vm
["uuid"])
2546 except db_base_Exception
as e
:
2547 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2548 # 2.2. Update in openmano DB the interface VMs
2549 for interface
in interfaces
:
2550 #translate from vim_net_id to instance_net_id
2552 for net
in instanceDict
['nets']:
2553 if net
["vim_net_id"] == interface
["vim_net_id"]:
2554 network_id_list
.append(net
["uuid"])
2555 if not network_id_list
:
2557 del interface
["vim_net_id"]
2559 for network_id
in network_id_list
:
2560 mydb
.update_rows('instance_interfaces', UPDATE
=interface
, WHERE
={'instance_vm_id':vm
["uuid"], "instance_net_id":network_id
})
2561 except db_base_Exception
as e
:
2562 logger
.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm
["uuid"], network_id
)
2564 # 3. Getting the status of all nets
2566 for datacenter_key
in myvims
:
2567 if not net_list
.get(datacenter_key
):
2571 if not myvims
[datacenter_key
]:
2572 failed_message
= "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"])
2575 net_dict
.update(myvims
[datacenter_key
].refresh_nets_status(net_list
[datacenter_key
]) )
2577 except vimconn
.vimconnException
as e
:
2578 logger
.error("VIM exception %s %s", type(e
).__name
__, str(e
))
2579 failed_message
= str(e
)
2581 for net
in net_list
[datacenter_key
]:
2582 net_dict
[net
] = {'status': "VIM_ERROR", 'error_msg': failed_message
}
2584 # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
2585 # TODO: update nets inside a vnf
2586 for net
in instanceDict
['nets']:
2587 net_id
= net
['vim_net_id']
2588 if net_dict
[net_id
].get('error_msg') and len(net_dict
[net_id
]['error_msg']) >= 1024:
2589 net_dict
[net_id
]['error_msg'] = net_dict
[net_id
]['error_msg'][:516] + " ... " + net_dict
[vm_id
]['error_msg'][-500:]
2590 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'):
2591 net
['status'] = net_dict
[net_id
]['status']
2592 net
['error_msg'] = net_dict
[net_id
].get('error_msg')
2593 net
['vim_info'] = net_dict
[net_id
].get('vim_info')
2594 # 5.1. Update in openmano DB the nets whose status changed
2596 updated
= mydb
.update_rows('instance_nets', UPDATE
=net_dict
[net_id
], WHERE
={'uuid':net
["uuid"]})
2597 nets_notupdated
.remove(net
["uuid"])
2599 nets_updated
.append(net
["uuid"])
2600 except db_base_Exception
as e
:
2601 logger
.error("nfvo.refresh_instance error database update: %s", str(e
))
2603 # Returns appropriate output
2604 #print "nfvo.refresh_instance finishes"
2605 logger
.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
2606 str(vms_updated
), str(nets_updated
), str(vms_notupdated
), str(nets_notupdated
))
2607 instance_id
= instanceDict
['uuid']
2608 if len(vms_notupdated
)+len(nets_notupdated
)>0:
2609 error_msg
= "VMs not updated: " + str(vms_notupdated
) + "; nets not updated: " + str(nets_notupdated
)
2610 return len(vms_notupdated
)+len(nets_notupdated
), 'Scenario instance ' + instance_id
+ ' refreshed but some elements could not be updated in the database: ' + error_msg
2612 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
2615 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
2616 #print "Checking that the instance_id exists and getting the instance dictionary"
2617 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
2618 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
2620 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2621 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
2623 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
2624 myvim
= vims
.values()[0]
2627 input_vnfs
= action_dict
.pop("vnfs", [])
2628 input_vms
= action_dict
.pop("vms", [])
2629 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
2633 for sce_vnf
in instanceDict
['vnfs']:
2634 for vm
in sce_vnf
['vms']:
2635 if not action_over_all
:
2636 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
2637 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
2640 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
2641 if "console" in action_dict
:
2642 if not global_config
["http_console_proxy"]:
2643 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2644 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2645 protocol
=data
["protocol"],
2646 ip
= data
["server"],
2647 port
= data
["port"],
2648 suffix
= data
["suffix"]),
2652 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
2653 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
2654 "description": "this console is only reachable by local interface",
2659 #print "console data", data
2661 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
2662 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
2663 "description": "{protocol}//{ip}:{port}/{suffix}".format(
2664 protocol
=data
["protocol"],
2665 ip
= global_config
["http_console_host"],
2666 port
= console_thread
.port
,
2667 suffix
= data
["suffix"]),
2671 except NfvoException
as e
:
2672 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2676 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
2678 except vimconn
.vimconnException
as e
:
2679 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
2682 if vm_ok
==0: #all goes wrong
2688 def create_or_use_console_proxy_thread(console_server
, console_port
):
2689 #look for a non-used port
2690 console_thread_key
= console_server
+ ":" + str(console_port
)
2691 if console_thread_key
in global_config
["console_thread"]:
2692 #global_config["console_thread"][console_thread_key].start_timeout()
2693 return global_config
["console_thread"][console_thread_key
]
2695 for port
in global_config
["console_port_iterator"]():
2696 #print "create_or_use_console_proxy_thread() port:", port
2697 if port
in global_config
["console_ports"]:
2700 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
2702 global_config
["console_thread"][console_thread_key
] = clithread
2703 global_config
["console_ports"][port
] = console_thread_key
2705 except cli
.ConsoleProxyExceptionPortUsed
as e
:
2706 #port used, try with onoher
2708 except cli
.ConsoleProxyException
as e
:
2709 raise NfvoException(str(e
), HTTP_Bad_Request
)
2710 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
2713 def check_tenant(mydb
, tenant_id
):
2714 '''check that tenant exists at database'''
2715 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
2717 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
2721 def new_tenant(mydb
, tenant_dict
):
2722 tenant_id
= mydb
.new_row("nfvo_tenants", tenant_dict
, add_uuid
=True)
2726 def delete_tenant(mydb
, tenant
):
2727 #get nfvo_tenant info
2729 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
2730 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
2731 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
2734 def new_datacenter(mydb
, datacenter_descriptor
):
2735 if "config" in datacenter_descriptor
:
2736 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
2737 #Check that datacenter-type is correct
2738 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
2741 module
= "vimconn_" + datacenter_type
2742 module_info
= imp
.find_module(module
)
2743 except (IOError, ImportError):
2744 if module_info
and module_info
[0]:
2745 file.close(module_info
[0])
2746 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
2748 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True)
2749 return datacenter_id
2752 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
2753 #obtain data, check that only one exist
2754 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
2756 datacenter_id
= datacenter
['uuid']
2757 where
={'uuid': datacenter
['uuid']}
2758 if "config" in datacenter_descriptor
:
2759 if datacenter_descriptor
['config']!=None:
2761 new_config_dict
= datacenter_descriptor
["config"]
2764 for k
in new_config_dict
:
2765 if new_config_dict
[k
]==None:
2768 config_text
= datacenter
.get("config")
2771 config_dict
= yaml
.load(config_text
)
2772 config_dict
.update(new_config_dict
)
2776 except Exception as e
:
2777 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
2778 datacenter_descriptor
["config"]= yaml
.safe_dump(config_dict
,default_flow_style
=True,width
=256) if len(config_dict
)>0 else None
2779 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
2780 return datacenter_id
2783 def delete_datacenter(mydb
, datacenter
):
2784 #get nfvo_tenant info
2785 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
2786 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
2787 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
2790 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):
2791 #get datacenter info
2792 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2793 datacenter_name
= myvim
["name"]
2795 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
2797 # get nfvo_tenant info
2798 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
2799 if vim_tenant_name
==None:
2800 vim_tenant_name
=tenant_dict
['name']
2802 #check that this association does not exist before
2803 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
2804 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2805 if len(tenants_datacenters
)>0:
2806 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
2808 vim_tenant_id_exist_atdb
=False
2809 if not create_vim_tenant
:
2810 where_
={"datacenter_id": datacenter_id
}
2811 if vim_tenant_id
!=None:
2812 where_
["vim_tenant_id"] = vim_tenant_id
2813 if vim_tenant_name
!=None:
2814 where_
["vim_tenant_name"] = vim_tenant_name
2815 #check if vim_tenant_id is already at database
2816 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
2817 if len(datacenter_tenants_dict
)>=1:
2818 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
2819 vim_tenant_id_exist_atdb
=True
2820 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
2822 datacenter_tenants_dict
= {}
2823 #insert at table datacenter_tenants
2824 else: #if vim_tenant_id==None:
2825 #create tenant at VIM if not provided
2827 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
2828 except vimconn
.vimconnException
as e
:
2829 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
2830 datacenter_tenants_dict
= {}
2831 datacenter_tenants_dict
["created"]="true"
2833 #fill datacenter_tenants table
2834 if not vim_tenant_id_exist_atdb
:
2835 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
2836 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
2837 datacenter_tenants_dict
["user"] = vim_username
2838 datacenter_tenants_dict
["passwd"] = vim_password
2839 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
2841 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
2842 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True)
2843 datacenter_tenants_dict
["uuid"] = id_
2845 #fill tenants_datacenters table
2846 tenants_datacenter_dict
["datacenter_tenant_id"]=datacenter_tenants_dict
["uuid"]
2847 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
2849 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
2850 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
2851 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, db
=db
, db_lock
=db_lock
, ovim
=ovim
)
2853 thread_id
= datacenter_id
+ "." + tenant_dict
['uuid']
2854 vim_threads
["running"][thread_id
] = new_thread
2855 return datacenter_id
2857 def edit_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=None, vim_tenant_name
=None, vim_username
=None, vim_password
=None, config
=None):
2858 #Obtain the data of this datacenter_tenant_id
2859 vim_data
= mydb
.get_rows(
2860 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
2861 "datacenter_tenants.passwd", "datacenter_tenants.config"),
2862 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
2863 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
2864 "tenants_datacenters.datacenter_id": datacenter_id
})
2866 logger
.debug(str(vim_data
))
2867 if len(vim_data
) < 1:
2868 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
2872 v
['config'] = yaml
.load(v
['config'])
2875 v
['vim_tenant_id'] = vim_tenant_id
2877 v
['vim_tenant_name'] = vim_tenant_name
2879 v
['user'] = vim_username
2881 v
['passwd'] = vim_password
2885 v
['config'].update(config
)
2887 logger
.debug(str(v
))
2888 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
2889 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
2890 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
2892 return datacenter_id
2894 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
2895 #get datacenter info
2896 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
)
2898 #get nfvo_tenant info
2899 if not tenant_id
or tenant_id
=="any":
2902 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
2903 tenant_uuid
= tenant_dict
['uuid']
2905 #check that this association exist before
2906 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
2908 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
2909 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2910 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
2911 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
2913 #delete this association
2914 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
2916 #get vim_tenant info and deletes
2918 for tenant_datacenter_item
in tenant_datacenter_list
:
2919 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2920 #try to delete vim:tenant
2922 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
2923 if vim_tenant_dict
['created']=='true':
2924 #delete tenant at VIM if created by NFVO
2926 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
2927 except vimconn
.vimconnException
as e
:
2928 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
2929 logger
.warn(warning
)
2930 except db_base_Exception
as e
:
2931 logger
.error("Cannot delete datacenter_tenants " + str(e
))
2932 pass # the error will be caused because dependencies, vim_tenant can not be deleted
2933 thread_id
= datacenter_id
+ "." + tenant_datacenter_item
["nfvo_tenant_id"]
2934 thread
= vim_threads
["running"][thread_id
]
2935 thread
.insert_task(new_task("exit", None, store
=False))
2936 vim_threads
["deleting"][thread_id
] = thread
2937 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
2940 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
2942 #get datacenter info
2943 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2945 if 'net-update' in action_dict
:
2947 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
2949 except vimconn
.vimconnException
as e
:
2950 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
2951 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
2952 #update nets Change from VIM format to NFVO format
2955 net_nfvo
={'datacenter_id': datacenter_id
}
2956 net_nfvo
['name'] = net
['name']
2957 #net_nfvo['description']= net['name']
2958 net_nfvo
['vim_net_id'] = net
['id']
2959 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
2960 net_nfvo
['shared'] = net
['shared']
2961 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
2962 net_list
.append(net_nfvo
)
2963 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
2964 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
2966 elif 'net-edit' in action_dict
:
2967 net
= action_dict
['net-edit'].pop('net')
2968 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2969 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
2970 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2972 elif 'net-delete' in action_dict
:
2973 net
= action_dict
['net-deelte'].get('net')
2974 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
2975 result
= mydb
.delete_row(FROM
='datacenter_nets',
2976 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
2980 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
2983 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
2984 #get datacenter info
2985 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2987 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
2988 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
2989 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
2993 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
2994 #get datacenter info
2995 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2998 action_dict
= action_dict
["netmap"]
2999 if 'vim_id' in action_dict
:
3000 filter_dict
["id"] = action_dict
['vim_id']
3001 if 'vim_name' in action_dict
:
3002 filter_dict
["name"] = action_dict
['vim_name']
3004 filter_dict
["shared"] = True
3007 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
3008 except vimconn
.vimconnException
as e
:
3009 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
3010 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3011 if len(vim_nets
)>1 and action_dict
:
3012 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
3013 elif len(vim_nets
)==0: # and action_dict:
3014 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
3016 for net
in vim_nets
:
3017 net_nfvo
={'datacenter_id': datacenter_id
}
3018 if action_dict
and "name" in action_dict
:
3019 net_nfvo
['name'] = action_dict
['name']
3021 net_nfvo
['name'] = net
['name']
3022 #net_nfvo['description']= net['name']
3023 net_nfvo
['vim_net_id'] = net
['id']
3024 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3025 net_nfvo
['shared'] = net
['shared']
3026 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3028 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
3029 net_nfvo
["status"] = "OK"
3030 net_nfvo
["uuid"] = net_id
3031 except db_base_Exception
as e
:
3035 net_nfvo
["status"] = "FAIL: " + str(e
)
3036 net_list
.append(net_nfvo
)
3040 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
3041 #get datacenter info
3042 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3045 if utils
.check_valid_uuid(name
):
3046 filter_dict
["id"] = name
3048 filter_dict
["name"] = name
3050 if item
=="networks":
3051 #filter_dict['tenant_id'] = myvim['tenant_id']
3052 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
3053 elif item
=="tenants":
3054 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
3055 elif item
== "images":
3056 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
3058 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3059 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
3060 if name
and len(content
)==1:
3061 return {item
[:-1]: content
[0]}
3062 elif name
and len(content
)==0:
3063 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
3066 return {item
: content
}
3067 except vimconn
.vimconnException
as e
:
3068 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
3069 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
3072 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
3073 #get datacenter info
3074 if tenant_id
== "any":
3077 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3079 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
3080 logger
.debug("vim_action_delete vim response: " + str(content
))
3081 items
= content
.values()[0]
3082 if type(items
)==list and len(items
)==0:
3083 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
3084 elif type(items
)==list and len(items
)>1:
3085 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
3086 else: # it is a dict
3087 item_id
= items
["id"]
3088 item_name
= str(items
.get("name"))
3091 if item
=="networks":
3092 content
= myvim
.delete_network(item_id
)
3093 elif item
=="tenants":
3094 content
= myvim
.delete_tenant(item_id
)
3095 elif item
== "images":
3096 content
= myvim
.delete_image(item_id
)
3098 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3099 except vimconn
.vimconnException
as e
:
3100 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
3101 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
3103 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
3106 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
3107 #get datacenter info
3108 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
3109 if tenant_id
== "any":
3111 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3113 if item
=="networks":
3114 net
= descriptor
["network"]
3115 net_name
= net
.pop("name")
3116 net_type
= net
.pop("type", "bridge")
3117 net_public
= net
.pop("shared", False)
3118 net_ipprofile
= net
.pop("ip_profile", None)
3119 net_vlan
= net
.pop("vlan", None)
3120 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
3121 elif item
=="tenants":
3122 tenant
= descriptor
["tenant"]
3123 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
3125 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
3126 except vimconn
.vimconnException
as e
:
3127 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
3129 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
3131 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
3132 #data = ovim.new_of_controller(sdn_controller)
3134 logger
.debug('New SDN controller created with uuid {}'.format(data
))
3137 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
3138 #data = ovim.edit_of_controller(controller_id, sdn_controller)
3140 msg
= 'SDN controller {} updated'.format(data
)
3144 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
3145 if controller_id
== None:
3146 #data = ovim.get_of_controllers()
3149 #data = ovim.show_of_controller(controller_id)
3150 data
= {'dpid': None}
3151 msg
= 'SDN controller list:\n {}'.format(data
)
3155 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
3156 select_
= ('uuid', 'config')
3157 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
3158 for datacenter
in datacenters
:
3159 if datacenter
['config']:
3160 config
= yaml
.load(datacenter
['config'])
3161 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
3162 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
3164 #data = ovim.delete_of_controller(controller_id)
3166 msg
= 'SDN controller {} deleted'.format(data
)
3170 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
3171 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
3172 if len(controller
) < 1:
3173 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
3176 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
3178 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
3180 #sdn_controller = ovim.show_of_controller(sdn_controller_id)
3181 #switch_dpid = sdn_controller["dpid"]
3184 for compute_node
in sdn_port_mapping
:
3185 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
3187 element
["compute_node"] = compute_node
["compute_node"]
3188 for port
in compute_node
["ports"]:
3189 element
["pci"] = port
.get("pci")
3190 element
["switch_port"] = port
.get("switch_port")
3191 element
["switch_mac"] = port
.get("switch_mac")
3192 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
3193 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
3194 " or 'switch_mac'", HTTP_Bad_Request
)
3195 maps
.append(dict(element
))
3197 #return ovim.set_of_port_mapping(maps, ofc_id=sdn_controller_id, switch_dpid=switch_dpid, region=datacenter_id)
3200 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
3201 #maps = ovim.get_of_port_mappings(db_filter={"region": datacenter_id})
3205 "sdn-controller": None,
3206 "datacenter-id": datacenter_id
,
3208 "ports_mapping": list()
3211 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
3212 if datacenter
['config']:
3213 config
= yaml
.load(datacenter
['config'])
3214 if 'sdn-controller' in config
:
3215 controller_id
= config
['sdn-controller']
3216 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
3217 result
["sdn-controller"] = controller_id
3218 result
["dpid"] = sdn_controller
["dpid"]
3220 # if result["sdn-controller"] == None or result["dpid"] == None:
3221 # raise NfvoException("Not all SDN controller information for datacenter {} could be found: {}".format(datacenter_id, result),
3222 # HTTP_Internal_Server_Error)
3227 ports_correspondence_dict
= dict()
3229 if result
["sdn-controller"] != link
["ofc_id"]:
3230 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
3231 if result
["dpid"] != link
["switch_dpid"]:
3232 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
3234 element
["pci"] = link
["pci"]
3235 if link
["switch_port"]:
3236 element
["switch_port"] = link
["switch_port"]
3237 if link
["switch_mac"]:
3238 element
["switch_mac"] = link
["switch_mac"]
3240 if not link
["compute_node"] in ports_correspondence_dict
:
3242 content
["compute_node"] = link
["compute_node"]
3243 content
["ports"] = list()
3244 ports_correspondence_dict
[link
["compute_node"]] = content
3246 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
3248 for key
in sorted(ports_correspondence_dict
):
3249 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
3253 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
3254 #return ovim.clear_of_port_mapping(db_filter={"region":datacenter_id})