1 # -*- coding: utf-8 -*-
4 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
5 # This file is part of openmano
8 # Licensed under the Apache License, Version 2.0 (the "License"); you may
9 # not use this file except in compliance with the License. You may obtain
10 # a copy of the License at
12 # http://www.apache.org/licenses/LICENSE-2.0
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17 # License for the specific language governing permissions and limitations
20 # For those usages not covered by the Apache License, Version 2.0 please
21 # contact with: nfvlabs@tid.es
25 NFVO engine, implementing all the methods for the creation, deletion and management of vnfs, scenarios and instances
27 __author__
="Alfonso Tierno, Gerardo Garcia, Pablo Montes"
28 __date__
="$16-sep-2014 22:05:01$"
35 from db_base
import HTTP_Unauthorized
, HTTP_Bad_Request
, HTTP_Internal_Server_Error
, HTTP_Not_Found
,\
36 HTTP_Conflict
, HTTP_Method_Not_Allowed
37 import console_proxy_thread
as cli
41 from uuid
import uuid4
42 from db_base
import db_base_Exception
45 from threading
import Lock
47 from lib_osm_openvim
import ovim
as ovim_module
48 from lib_osm_openvim
.ovim
import ovimException
49 from Crypto
.PublicKey
import RSA
51 import osm_im
.vnfd
as vnfd_catalog
52 import osm_im
.nsd
as nsd_catalog
53 from pyangbind
.lib
.serialise
import pybindJSONDecoder
54 from itertools
import chain
57 global vimconn_imported
59 global default_volume_size
60 default_volume_size
= '5' #size in GB
65 vimconn_imported
= {} # dictionary with VIM type as key, loaded module as value
66 vim_threads
= {"running":{}, "deleting": {}, "names": []} # threads running for attached-VIMs
67 vim_persistent_info
= {}
68 logger
= logging
.getLogger('openmano.nfvo')
74 class NfvoException(Exception):
75 def __init__(self
, message
, http_code
):
76 self
.http_code
= http_code
77 Exception.__init
__(self
, message
)
83 if task_id
<= last_task_id
:
84 task_id
= last_task_id
+ 0.000001
85 last_task_id
= task_id
86 return "ACTION-{:.6f}".format(task_id
)
87 # return (t.strftime("%Y%m%dT%H%M%S.{}%Z", t.localtime(task_id))).format(int((task_id % 1)*1e6))
90 def new_task(name
, params
, depends
=None):
92 task_id
= get_task_id()
93 task
= {"status": "enqueued", "id": task_id
, "name": name
, "params": params
}
95 task
["depends"] = depends
100 return True if id[:5] == "TASK-" else False
103 def get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_name
, tenant_id
):
104 name
= datacenter_name
[:16]
105 if name
not in vim_threads
["names"]:
106 vim_threads
["names"].append(name
)
108 name
= datacenter_name
[:16] + "." + tenant_name
[:16]
109 if name
not in vim_threads
["names"]:
110 vim_threads
["names"].append(name
)
112 name
= datacenter_id
+ "-" + tenant_id
113 vim_threads
["names"].append(name
)
117 def start_service(mydb
):
118 global db
, global_config
119 db
= nfvo_db
.nfvo_db()
120 db
.connect(global_config
['db_host'], global_config
['db_user'], global_config
['db_passwd'], global_config
['db_name'])
123 # Initialize openvim for SDN control
124 # TODO: Avoid static configuration by adding new parameters to openmanod.cfg
125 # TODO: review ovim.py to delete not needed configuration
126 ovim_configuration
= {
127 'logger_name': 'openmano.ovim',
128 'network_vlan_range_start': 1000,
129 'network_vlan_range_end': 4096,
130 'db_name': global_config
["db_ovim_name"],
131 'db_host': global_config
["db_ovim_host"],
132 'db_user': global_config
["db_ovim_user"],
133 'db_passwd': global_config
["db_ovim_passwd"],
136 'network_type': 'bridge',
137 #TODO: log_level_of should not be needed. To be modified in ovim
138 'log_level_of': 'DEBUG'
141 ovim
= ovim_module
.ovim(ovim_configuration
)
144 from_
= 'tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join '\
145 'datacenter_tenants as dt on td.datacenter_tenant_id=dt.uuid'
146 select_
= ('type', 'd.config as config', 'd.uuid as datacenter_id', 'vim_url', 'vim_url_admin',
147 'd.name as datacenter_name', 'dt.uuid as datacenter_tenant_id',
148 'dt.vim_tenant_name as vim_tenant_name', 'dt.vim_tenant_id as vim_tenant_id',
149 'user', 'passwd', 'dt.config as dt_config', 'nfvo_tenant_id')
150 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
)
152 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
153 'datacenter_id': vim
.get('datacenter_id')}
155 extra
.update(yaml
.load(vim
["config"]))
156 if vim
.get('dt_config'):
157 extra
.update(yaml
.load(vim
["dt_config"]))
158 if vim
["type"] not in vimconn_imported
:
161 module
= "vimconn_" + vim
["type"]
162 pkg
= __import__("osm_ro." + module
)
163 vim_conn
= getattr(pkg
, module
)
164 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
165 # vim_conn = imp.load_module(vim["type"], *module_info)
166 vimconn_imported
[vim
["type"]] = vim_conn
167 except (IOError, ImportError) as e
:
168 # if module_info and module_info[0]:
169 # file.close(module_info[0])
170 raise NfvoException("Unknown vim type '{}'. Cannot open file '{}.py'; {}: {}".format(
171 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
173 thread_id
= vim
['datacenter_tenant_id']
174 vim_persistent_info
[thread_id
] = {}
177 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
178 myvim
= vimconn_imported
[ vim
["type"] ].vimconnector(
179 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
180 tenant_id
=vim
['vim_tenant_id'], tenant_name
=vim
['vim_tenant_name'],
181 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
182 user
=vim
['user'], passwd
=vim
['passwd'],
183 config
=extra
, persistent_info
=vim_persistent_info
[thread_id
]
185 except vimconn
.vimconnException
as e
:
187 logger
.error("Cannot launch thread for VIM {} '{}': {}".format(vim
['datacenter_name'],
188 vim
['datacenter_id'], e
))
189 except Exception as e
:
190 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, e
),
191 HTTP_Internal_Server_Error
)
192 thread_name
= get_non_used_vim_name(vim
['datacenter_name'], vim
['vim_tenant_id'], vim
['vim_tenant_name'],
193 vim
['vim_tenant_id'])
194 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, vim
['datacenter_name'],
195 vim
['datacenter_tenant_id'], db
=db
, db_lock
=db_lock
, ovim
=ovim
)
197 vim_threads
["running"][thread_id
] = new_thread
198 except db_base_Exception
as e
:
199 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
200 except ovim_module
.ovimException
as e
:
202 if message
[:22] == "DATABASE wrong version":
203 message
= "DATABASE wrong version of lib_osm_openvim {msg} -d{dbname} -u{dbuser} -p{dbpass} {ver}' "\
204 "at host {dbhost}".format(
205 msg
=message
[22:-3], dbname
=global_config
["db_ovim_name"],
206 dbuser
=global_config
["db_ovim_user"], dbpass
=global_config
["db_ovim_passwd"],
207 ver
=message
[-3:-1], dbhost
=global_config
["db_ovim_host"])
208 raise NfvoException(message
, HTTP_Bad_Request
)
212 global ovim
, global_config
215 for thread_id
,thread
in vim_threads
["running"].items():
216 thread
.insert_task("exit")
217 vim_threads
["deleting"][thread_id
] = thread
218 vim_threads
["running"] = {}
219 if global_config
and global_config
.get("console_thread"):
220 for thread
in global_config
["console_thread"]:
221 thread
.terminate
= True
224 return ("openmanod version {} {}\n(c) Copyright Telefonica".format(global_config
["version"],
225 global_config
["version_date"] ))
228 def get_flavorlist(mydb
, vnf_id
, nfvo_tenant
=None):
230 return result, content:
231 <0, error_text upon error
232 nb_records, flavor_list on success
235 WHERE_dict
['vnf_id'] = vnf_id
236 if nfvo_tenant
is not None:
237 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
239 #result, content = mydb.get_table(FROM='vms join vnfs on vms.vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
240 #result, content = mydb.get_table(FROM='vms',SELECT=('vim_flavor_id',),WHERE=WHERE_dict )
241 flavors
= mydb
.get_rows(FROM
='vms join flavors on vms.flavor_id=flavors.uuid',SELECT
=('flavor_id',),WHERE
=WHERE_dict
)
242 #print "get_flavor_list result:", result
243 #print "get_flavor_list content:", content
245 for flavor
in flavors
:
246 flavorList
.append(flavor
['flavor_id'])
250 def get_imagelist(mydb
, vnf_id
, nfvo_tenant
=None):
252 return result, content:
253 <0, error_text upon error
254 nb_records, flavor_list on success
257 WHERE_dict
['vnf_id'] = vnf_id
258 if nfvo_tenant
is not None:
259 WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
261 #result, content = mydb.get_table(FROM='vms join vnfs on vms-vnf_id = vnfs.uuid',SELECT=('uuid'),WHERE=WHERE_dict )
262 images
= mydb
.get_rows(FROM
='vms join images on vms.image_id=images.uuid',SELECT
=('image_id',),WHERE
=WHERE_dict
)
265 imageList
.append(image
['image_id'])
269 def get_vim(mydb
, nfvo_tenant
=None, datacenter_id
=None, datacenter_name
=None, datacenter_tenant_id
=None,
270 vim_tenant
=None, vim_tenant_name
=None, vim_user
=None, vim_passwd
=None):
271 '''Obtain a dictionary of VIM (datacenter) classes with some of the input parameters
272 return dictionary with {datacenter_id: vim_class, ... }. vim_class contain:
273 'nfvo_tenant_id','datacenter_id','vim_tenant_id','vim_url','vim_url_admin','datacenter_name','type','user','passwd'
274 raise exception upon error
277 if nfvo_tenant
is not None: WHERE_dict
['nfvo_tenant_id'] = nfvo_tenant
278 if datacenter_id
is not None: WHERE_dict
['d.uuid'] = datacenter_id
279 if datacenter_tenant_id
is not None: WHERE_dict
['datacenter_tenant_id'] = datacenter_tenant_id
280 if datacenter_name
is not None: WHERE_dict
['d.name'] = datacenter_name
281 if vim_tenant
is not None: WHERE_dict
['dt.vim_tenant_id'] = vim_tenant
282 if vim_tenant_name
is not None: WHERE_dict
['vim_tenant_name'] = vim_tenant_name
283 if nfvo_tenant
or vim_tenant
or vim_tenant_name
or datacenter_tenant_id
:
284 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'
285 select_
= ('type','d.config as config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name',
286 'dt.uuid as datacenter_tenant_id','dt.vim_tenant_name as vim_tenant_name','dt.vim_tenant_id as vim_tenant_id',
287 'user','passwd', 'dt.config as dt_config')
289 from_
= 'datacenters as d'
290 select_
= ('type','config','d.uuid as datacenter_id', 'vim_url', 'vim_url_admin', 'd.name as datacenter_name')
292 vims
= mydb
.get_rows(FROM
=from_
, SELECT
=select_
, WHERE
=WHERE_dict
)
295 extra
={'datacenter_tenant_id': vim
.get('datacenter_tenant_id'),
296 'datacenter_id': vim
.get('datacenter_id')}
298 extra
.update(yaml
.load(vim
["config"]))
299 if vim
.get('dt_config'):
300 extra
.update(yaml
.load(vim
["dt_config"]))
301 if vim
["type"] not in vimconn_imported
:
304 module
= "vimconn_" + vim
["type"]
305 pkg
= __import__("osm_ro." + module
)
306 vim_conn
= getattr(pkg
, module
)
307 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
308 # vim_conn = imp.load_module(vim["type"], *module_info)
309 vimconn_imported
[vim
["type"]] = vim_conn
310 except (IOError, ImportError) as e
:
311 # if module_info and module_info[0]:
312 # file.close(module_info[0])
313 raise NfvoException("Unknown vim type '{}'. Can not open file '{}.py'; {}: {}".format(
314 vim
["type"], module
, type(e
).__name
__, str(e
)), HTTP_Bad_Request
)
317 if 'datacenter_tenant_id' in vim
:
318 thread_id
= vim
["datacenter_tenant_id"]
319 if thread_id
not in vim_persistent_info
:
320 vim_persistent_info
[thread_id
] = {}
321 persistent_info
= vim_persistent_info
[thread_id
]
325 # return -HTTP_Bad_Request, "You must provide a valid tenant name or uuid for VIM %s" % ( vim["type"])
326 vim_dict
[ vim
['datacenter_id'] ] = vimconn_imported
[ vim
["type"] ].vimconnector(
327 uuid
=vim
['datacenter_id'], name
=vim
['datacenter_name'],
328 tenant_id
=vim
.get('vim_tenant_id',vim_tenant
),
329 tenant_name
=vim
.get('vim_tenant_name',vim_tenant_name
),
330 url
=vim
['vim_url'], url_admin
=vim
['vim_url_admin'],
331 user
=vim
.get('user',vim_user
), passwd
=vim
.get('passwd',vim_passwd
),
332 config
=extra
, persistent_info
=persistent_info
334 except Exception as e
:
335 raise NfvoException("Error at VIM {}; {}: {}".format(vim
["type"], type(e
).__name
__, str(e
)), HTTP_Internal_Server_Error
)
337 except db_base_Exception
as e
:
338 raise NfvoException(str(e
) + " at nfvo.get_vim", e
.http_code
)
341 def rollback(mydb
, vims
, rollback_list
):
343 #delete things by reverse order
344 for i
in range(len(rollback_list
)-1, -1, -1):
345 item
= rollback_list
[i
]
346 if item
["where"]=="vim":
347 if item
["vim_id"] not in vims
:
349 if is_task_id(item
["uuid"]):
351 vim
= vims
[item
["vim_id"]]
353 if item
["what"]=="image":
354 vim
.delete_image(item
["uuid"])
355 mydb
.delete_row(FROM
="datacenters_images", WHERE
={"datacenter_vim_id": vim
["id"], "vim_id":item
["uuid"]})
356 elif item
["what"]=="flavor":
357 vim
.delete_flavor(item
["uuid"])
358 mydb
.delete_row(FROM
="datacenters_flavors", WHERE
={"datacenter_id": vim
["id"], "vim_id":item
["uuid"]})
359 elif item
["what"]=="network":
360 vim
.delete_network(item
["uuid"])
361 elif item
["what"]=="vm":
362 vim
.delete_vminstance(item
["uuid"])
363 except vimconn
.vimconnException
as e
:
364 logger
.error("Error in rollback. Not possible to delete VIM %s '%s'. Message: %s", item
['what'], item
["uuid"], str(e
))
365 undeleted_items
.append("{} {} from VIM {}".format(item
['what'], item
["uuid"], vim
["name"]))
366 except db_base_Exception
as e
:
367 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB.datacenters Message: %s", item
['what'], item
["uuid"], str(e
))
371 if item
["what"]=="image":
372 mydb
.delete_row(FROM
="images", WHERE
={"uuid": item
["uuid"]})
373 elif item
["what"]=="flavor":
374 mydb
.delete_row(FROM
="flavors", WHERE
={"uuid": item
["uuid"]})
375 except db_base_Exception
as e
:
376 logger
.error("Error in rollback. Not possible to delete %s '%s' from DB. Message: %s", item
['what'], item
["uuid"], str(e
))
377 undeleted_items
.append("{} '{}'".format(item
['what'], item
["uuid"]))
378 if len(undeleted_items
)==0:
379 return True," Rollback successful."
381 return False," Rollback fails to delete: " + str(undeleted_items
)
384 def check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1):
386 #create a dictionary with vnfc-name: vnfc:interface-list key:values pairs
388 for vnfc
in vnf_descriptor
["vnf"]["VNFC"]:
390 #dataplane interfaces
391 for numa
in vnfc
.get("numas",() ):
392 for interface
in numa
.get("interfaces",()):
393 if interface
["name"] in name_dict
:
395 "Error at vnf:VNFC[name:'{}']:numas:interfaces:name, interface name '{}' already used in this VNFC".format(
396 vnfc
["name"], interface
["name"]),
398 name_dict
[ interface
["name"] ] = "underlay"
400 for interface
in vnfc
.get("bridge-ifaces",() ):
401 if interface
["name"] in name_dict
:
403 "Error at vnf:VNFC[name:'{}']:bridge-ifaces:name, interface name '{}' already used in this VNFC".format(
404 vnfc
["name"], interface
["name"]),
406 name_dict
[ interface
["name"] ] = "overlay"
407 vnfc_interfaces
[ vnfc
["name"] ] = name_dict
408 # check bood-data info
409 # if "boot-data" in vnfc:
410 # # check that user-data is incompatible with users and config-files
411 # if (vnfc["boot-data"].get("users") or vnfc["boot-data"].get("config-files")) and vnfc["boot-data"].get("user-data"):
412 # raise NfvoException(
413 # "Error at vnf:VNFC:boot-data, fields 'users' and 'config-files' are not compatible with 'user-data'",
416 #check if the info in external_connections matches with the one in the vnfcs
418 for external_connection
in vnf_descriptor
["vnf"].get("external-connections",() ):
419 if external_connection
["name"] in name_list
:
421 "Error at vnf:external-connections:name, value '{}' already used as an external-connection".format(
422 external_connection
["name"]),
424 name_list
.append(external_connection
["name"])
425 if external_connection
["VNFC"] not in vnfc_interfaces
:
427 "Error at vnf:external-connections[name:'{}']:VNFC, value '{}' does not match any VNFC".format(
428 external_connection
["name"], external_connection
["VNFC"]),
431 if external_connection
["local_iface_name"] not in vnfc_interfaces
[ external_connection
["VNFC"] ]:
433 "Error at vnf:external-connections[name:'{}']:local_iface_name, value '{}' does not match any interface of this VNFC".format(
434 external_connection
["name"],
435 external_connection
["local_iface_name"]),
438 #check if the info in internal_connections matches with the one in the vnfcs
440 for internal_connection
in vnf_descriptor
["vnf"].get("internal-connections",() ):
441 if internal_connection
["name"] in name_list
:
443 "Error at vnf:internal-connections:name, value '%s' already used as an internal-connection".format(
444 internal_connection
["name"]),
446 name_list
.append(internal_connection
["name"])
447 #We should check that internal-connections of type "ptp" have only 2 elements
449 if len(internal_connection
["elements"])>2 and (internal_connection
.get("type") == "ptp" or internal_connection
.get("type") == "e-line"):
451 "Error at 'vnf:internal-connections[name:'{}']:elements', size must be 2 for a '{}' type. Consider change it to '{}' type".format(
452 internal_connection
["name"],
453 'ptp' if vnf_descriptor_version
==1 else 'e-line',
454 'data' if vnf_descriptor_version
==1 else "e-lan"),
456 for port
in internal_connection
["elements"]:
458 iface
= port
["local_iface_name"]
459 if vnf
not in vnfc_interfaces
:
461 "Error at vnf:internal-connections[name:'{}']:elements[]:VNFC, value '{}' does not match any VNFC".format(
462 internal_connection
["name"], vnf
),
464 if iface
not in vnfc_interfaces
[ vnf
]:
466 "Error at vnf:internal-connections[name:'{}']:elements[]:local_iface_name, value '{}' does not match any interface of this VNFC".format(
467 internal_connection
["name"], iface
),
469 return -HTTP_Bad_Request
,
470 if vnf_descriptor_version
==1 and "type" not in internal_connection
:
471 if vnfc_interfaces
[vnf
][iface
] == "overlay":
472 internal_connection
["type"] = "bridge"
474 internal_connection
["type"] = "data"
475 if vnf_descriptor_version
==2 and "implementation" not in internal_connection
:
476 if vnfc_interfaces
[vnf
][iface
] == "overlay":
477 internal_connection
["implementation"] = "overlay"
479 internal_connection
["implementation"] = "underlay"
480 if (internal_connection
.get("type") == "data" or internal_connection
.get("type") == "ptp" or \
481 internal_connection
.get("implementation") == "underlay") and vnfc_interfaces
[vnf
][iface
] == "overlay":
483 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
484 internal_connection
["name"],
485 iface
, 'bridge' if vnf_descriptor_version
==1 else 'overlay',
486 'data' if vnf_descriptor_version
==1 else 'underlay'),
488 if (internal_connection
.get("type") == "bridge" or internal_connection
.get("implementation") == "overlay") and \
489 vnfc_interfaces
[vnf
][iface
] == "underlay":
491 "Error at vnf:internal-connections[name:'{}']:elements[]:{}, interface of type {} connected to an {} network".format(
492 internal_connection
["name"], iface
,
493 'data' if vnf_descriptor_version
==1 else 'underlay',
494 'bridge' if vnf_descriptor_version
==1 else 'overlay'),
498 def create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=None):
500 if only_create_at_vim
:
501 image_mano_id
= image_dict
['uuid']
502 if return_on_error
== None:
503 return_on_error
= True
505 if image_dict
['location']:
506 images
= mydb
.get_rows(FROM
="images", WHERE
={'location':image_dict
['location'], 'metadata':image_dict
['metadata']})
508 images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name':image_dict
['universal_name'], 'checksum':image_dict
['checksum']})
510 image_mano_id
= images
[0]['uuid']
512 #create image in MANO DB
513 temp_image_dict
={'name':image_dict
['name'], 'description':image_dict
.get('description',None),
514 'location':image_dict
['location'], 'metadata':image_dict
.get('metadata',None),
515 'universal_name':image_dict
['universal_name'] , 'checksum':image_dict
['checksum']
517 #temp_image_dict['location'] = image_dict.get('new_location') if image_dict['location'] is None
518 image_mano_id
= mydb
.new_row('images', temp_image_dict
, add_uuid
=True)
519 rollback_list
.append({"where":"mano", "what":"image","uuid":image_mano_id
})
520 #create image at every vim
521 for vim_id
,vim
in vims
.iteritems():
522 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
523 image_created
="false"
525 image_db
= mydb
.get_rows(FROM
="datacenters_images",
526 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'image_id': image_mano_id
})
527 #look at VIM if this image exist
529 if image_dict
['location'] is not None:
530 image_vim_id
= vim
.get_image_id_from_path(image_dict
['location'])
533 filter_dict
['name'] = image_dict
['universal_name']
534 if image_dict
.get('checksum') != None:
535 filter_dict
['checksum'] = image_dict
['checksum']
536 #logger.debug('>>>>>>>> Filter dict: %s', str(filter_dict))
537 vim_images
= vim
.get_image_list(filter_dict
)
538 #logger.debug('>>>>>>>> VIM images: %s', str(vim_images))
539 if len(vim_images
) > 1:
540 raise vimconn
.vimconnException("More than one candidate VIM image found for filter: {}".format(str(filter_dict
)), HTTP_Conflict
)
541 elif len(vim_images
) == 0:
542 raise vimconn
.vimconnNotFoundException("Image not found at VIM with filter: '{}'".format(str(filter_dict
)))
544 #logger.debug('>>>>>>>> VIM image 0: %s', str(vim_images[0]))
545 image_vim_id
= vim_images
[0]['id']
547 except vimconn
.vimconnNotFoundException
as e
:
548 #Create the image in VIM only if image_dict['location'] or image_dict['new_location'] is not None
550 #image_dict['location']=image_dict.get('new_location') if image_dict['location'] is None
551 if image_dict
['location']:
552 image_vim_id
= vim
.new_image(image_dict
)
553 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"image","uuid":image_vim_id
})
556 #If we reach this point, then the image has image name, and optionally checksum, and could not be found
557 raise vimconn
.vimconnException(str(e
))
558 except vimconn
.vimconnException
as e
:
560 logger
.error("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
563 logger
.warn("Error creating image at VIM '%s': %s", vim
["name"], str(e
))
565 except vimconn
.vimconnException
as e
:
567 logger
.error("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
569 logger
.warn("Error contacting VIM to know if the image exists at VIM: %s", str(e
))
572 #if we reach here, the image has been created or existed
574 #add new vim_id at datacenters_images
575 mydb
.new_row('datacenters_images', {'datacenter_vim_id': datacenter_vim_id
,
576 'image_id':image_mano_id
,
577 'vim_id': image_vim_id
,
578 'created':image_created
})
579 elif image_db
[0]["vim_id"]!=image_vim_id
:
580 #modify existing vim_id at datacenters_images
581 mydb
.update_rows('datacenters_images', UPDATE
={'vim_id':image_vim_id
}, WHERE
={'datacenter_vim_id':vim_id
, 'image_id':image_mano_id
})
583 return image_vim_id
if only_create_at_vim
else image_mano_id
586 def create_or_use_flavor(mydb
, vims
, flavor_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
= None):
587 temp_flavor_dict
= {'disk':flavor_dict
.get('disk',1),
588 'ram':flavor_dict
.get('ram'),
589 'vcpus':flavor_dict
.get('vcpus'),
591 if 'extended' in flavor_dict
and flavor_dict
['extended']==None:
592 del flavor_dict
['extended']
593 if 'extended' in flavor_dict
:
594 temp_flavor_dict
['extended']=yaml
.safe_dump(flavor_dict
['extended'],default_flow_style
=True,width
=256)
596 #look if flavor exist
597 if only_create_at_vim
:
598 flavor_mano_id
= flavor_dict
['uuid']
599 if return_on_error
== None:
600 return_on_error
= True
602 flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
604 flavor_mano_id
= flavors
[0]['uuid']
607 #create one by one the images of aditional disks
608 dev_image_list
=[] #list of images
609 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None:
611 for device
in flavor_dict
['extended'].get('devices',[]):
612 if "image" not in device
and "image name" not in device
:
615 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
616 image_dict
['universal_name']=device
.get('image name')
617 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
618 image_dict
['location']=device
.get('image')
619 #image_dict['new_location']=vnfc.get('image location')
620 image_dict
['checksum']=device
.get('image checksum')
621 image_metadata_dict
= device
.get('image metadata', None)
622 image_metadata_str
= None
623 if image_metadata_dict
!= None:
624 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
625 image_dict
['metadata']=image_metadata_str
626 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
627 #print "Additional disk image id for VNFC %s: %s" % (flavor_dict['name']+str(dev_nb)+"-img", image_id)
628 dev_image_list
.append(image_id
)
630 temp_flavor_dict
['name'] = flavor_dict
['name']
631 temp_flavor_dict
['description'] = flavor_dict
.get('description',None)
632 content
= mydb
.new_row('flavors', temp_flavor_dict
, add_uuid
=True)
633 flavor_mano_id
= content
634 rollback_list
.append({"where":"mano", "what":"flavor","uuid":flavor_mano_id
})
635 #create flavor at every vim
636 if 'uuid' in flavor_dict
:
637 del flavor_dict
['uuid']
639 for vim_id
,vim
in vims
.items():
640 datacenter_vim_id
= vim
["config"]["datacenter_tenant_id"]
641 flavor_created
="false"
643 flavor_db
= mydb
.get_rows(FROM
="datacenters_flavors",
644 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
645 #look at VIM if this flavor exist SKIPPED
646 #res_vim, flavor_vim_id = vim.get_flavor_id_from_path(flavor_dict['location'])
648 # print "Error contacting VIM to know if the flavor %s existed previously." %flavor_vim_id
652 # Create the flavor in VIM
653 # Translate images at devices from MANO id to VIM id
655 if 'extended' in flavor_dict
and flavor_dict
['extended']!=None and "devices" in flavor_dict
['extended']:
656 # make a copy of original devices
659 for device
in flavor_dict
["extended"].get("devices",[]):
662 devices_original
.append(dev
)
663 if 'image' in device
:
665 if 'image metadata' in device
:
666 del device
['image metadata']
667 if 'image checksum' in device
:
668 del device
['image checksum']
670 for index
in range(0,len(devices_original
)) :
671 device
=devices_original
[index
]
672 if "image" not in device
and "image name" not in device
:
674 disk_list
.append({'size': device
.get('size', default_volume_size
)})
677 image_dict
['name']=device
.get('image name',flavor_dict
['name']+str(dev_nb
)+"-img")
678 image_dict
['universal_name']=device
.get('image name')
679 image_dict
['description']=flavor_dict
['name']+str(dev_nb
)+"-img"
680 image_dict
['location']=device
.get('image')
681 # image_dict['new_location']=device.get('image location')
682 image_dict
['checksum']=device
.get('image checksum')
683 image_metadata_dict
= device
.get('image metadata', None)
684 image_metadata_str
= None
685 if image_metadata_dict
!= None:
686 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
687 image_dict
['metadata']=image_metadata_str
688 image_mano_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=False, return_on_error
=return_on_error
)
689 image_dict
["uuid"]=image_mano_id
690 image_vim_id
=create_or_use_image(mydb
, vims
, image_dict
, rollback_list
, only_create_at_vim
=True, return_on_error
=return_on_error
)
692 #save disk information (image must be based on and size
693 disk_list
.append({'image_id': image_vim_id
, 'size': device
.get('size', default_volume_size
)})
695 flavor_dict
["extended"]["devices"][index
]['imageRef']=image_vim_id
698 #check that this vim_id exist in VIM, if not create
699 flavor_vim_id
=flavor_db
[0]["vim_id"]
701 vim
.get_flavor(flavor_vim_id
)
702 continue #flavor exist
703 except vimconn
.vimconnException
:
705 #create flavor at vim
706 logger
.debug("nfvo.create_or_use_flavor() adding flavor to VIM %s", vim
["name"])
709 flavor_vim_id
=vim
.get_flavor_id_from_data(flavor_dict
)
710 flavor_create
="false"
711 except vimconn
.vimconnException
as e
:
714 if not flavor_vim_id
:
715 flavor_vim_id
= vim
.new_flavor(flavor_dict
)
716 rollback_list
.append({"where":"vim", "vim_id": vim_id
, "what":"flavor","uuid":flavor_vim_id
})
717 flavor_created
="true"
718 except vimconn
.vimconnException
as e
:
720 logger
.error("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
722 logger
.warn("Error creating flavor at VIM %s: %s.", vim
["name"], str(e
))
725 #if reach here the flavor has been create or exist
726 if len(flavor_db
)==0:
727 #add new vim_id at datacenters_flavors
728 extended_devices_yaml
= None
729 if len(disk_list
) > 0:
730 extended_devices
= dict()
731 extended_devices
['disks'] = disk_list
732 extended_devices_yaml
= yaml
.safe_dump(extended_devices
,default_flow_style
=True,width
=256)
733 mydb
.new_row('datacenters_flavors',
734 {'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
, 'vim_id': flavor_vim_id
,
735 'created': flavor_created
, 'extended': extended_devices_yaml
})
736 elif flavor_db
[0]["vim_id"]!=flavor_vim_id
:
737 #modify existing vim_id at datacenters_flavors
738 mydb
.update_rows('datacenters_flavors', UPDATE
={'vim_id':flavor_vim_id
},
739 WHERE
={'datacenter_vim_id': datacenter_vim_id
, 'flavor_id': flavor_mano_id
})
741 return flavor_vim_id
if only_create_at_vim
else flavor_mano_id
744 def get_str(obj
, field
, length
):
746 Obtain the str value,
751 value
= obj
.get(field
)
752 if value
is not None:
753 value
= str(value
)[:length
]
756 def _lookfor_or_create_image(db_image
, mydb
, descriptor
):
758 fill image content at db_image dictionary. Check if the image with this image and checksum exist
759 :param db_image: dictionary to insert data
760 :param mydb: database connector
761 :param descriptor: yang descriptor
762 :return: uuid if the image exist at DB, or None if a new image must be created with the data filled at db_image
765 db_image
["name"] = get_str(descriptor
, "image", 255)
766 db_image
["checksum"] = get_str(descriptor
, "image-checksum", 32)
767 if not db_image
["checksum"]: # Ensure that if empty string, None is stored
768 db_image
["checksum"] = None
769 if db_image
["name"].startswith("/"):
770 db_image
["location"] = db_image
["name"]
771 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'location': db_image
["location"]})
773 db_image
["universal_name"] = db_image
["name"]
774 existing_images
= mydb
.get_rows(FROM
="images", WHERE
={'universal_name': db_image
['universal_name'],
775 'checksum': db_image
['checksum']})
777 return existing_images
[0]["uuid"]
779 image_uuid
= str(uuid4())
780 db_image
["uuid"] = image_uuid
783 def new_vnfd_v3(mydb
, tenant_id
, vnf_descriptor
):
785 Parses an OSM IM vnfd_catalog and insert at DB
788 :param vnf_descriptor:
789 :return: The list of cretated vnf ids
792 myvnfd
= vnfd_catalog
.vnfd()
794 pybindJSONDecoder
.load_ietf_json(vnf_descriptor
, None, None, obj
=myvnfd
)
795 except Exception as e
:
796 raise NfvoException("Error. Invalid VNF descriptor format " + str(e
), HTTP_Bad_Request
)
806 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd:vnfd-catalog")
807 if not vnfd_catalog_descriptor
:
808 vnfd_catalog_descriptor
= vnf_descriptor
.get("vnfd-catalog")
809 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd")
810 if not vnfd_descriptor_list
:
811 vnfd_descriptor_list
= vnfd_catalog_descriptor
.get("vnfd:vnfd")
812 for vnfd_yang
in myvnfd
.vnfd_catalog
.vnfd
.itervalues():
813 vnfd
= vnfd_yang
.get()
816 vnf_uuid
= str(uuid4())
817 uuid_list
.append(vnf_uuid
)
818 vnfd_uuid_list
.append(vnf_uuid
)
821 "osm_id": get_str(vnfd
, "id", 255),
822 "name": get_str(vnfd
, "name", 255),
823 "description": get_str(vnfd
, "description", 255),
824 "tenant_id": tenant_id
,
825 "vendor": get_str(vnfd
, "vendor", 255),
826 "short_name": get_str(vnfd
, "short-name", 255),
827 "descriptor": str(vnf_descriptor
)[:60000]
830 for vnfd_descriptor
in vnfd_descriptor_list
:
831 if vnfd_descriptor
["id"] == str(vnfd
["id"]):
834 # table nets (internal-vld)
835 net_id2uuid
= {} # for mapping interface with network
836 for vld
in vnfd
.get("internal-vld").itervalues():
837 net_uuid
= str(uuid4())
838 uuid_list
.append(net_uuid
)
840 "name": get_str(vld
, "name", 255),
843 "description": get_str(vld
, "description", 255),
844 "type": "bridge", # TODO adjust depending on connection point type
846 net_id2uuid
[vld
.get("id")] = net_uuid
847 db_nets
.append(db_net
)
851 vdu_id2db_table_index
= {}
852 for vdu
in vnfd
.get("vdu").itervalues():
853 vm_uuid
= str(uuid4())
854 uuid_list
.append(vm_uuid
)
857 "osm_id": get_str(vdu
, "id", 255),
858 "name": get_str(vdu
, "name", 255),
859 "description": get_str(vdu
, "description", 255),
862 vdu_id2uuid
[db_vm
["osm_id"]] = vm_uuid
863 vdu_id2db_table_index
[db_vm
["osm_id"]] = db_vms_index
865 db_vm
["count"] = int(vdu
["count"])
868 image_present
= False
872 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, vdu
)
874 image_uuid
= db_image
["uuid"]
875 db_images
.append(db_image
)
876 db_vm
["image_id"] = image_uuid
880 if vdu
.get("volumes"):
881 for volume_key
in sorted(vdu
["volumes"]):
882 volume
= vdu
["volumes"][volume_key
]
883 if not image_present
:
884 # Convert the first volume to vnfc.image
887 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, volume
)
889 image_uuid
= db_image
["uuid"]
890 db_images
.append(db_image
)
891 db_vm
["image_id"] = image_uuid
893 # Add Openmano devices
895 device
["type"] = str(volume
.get("device-type"))
896 if volume
.get("size"):
897 device
["size"] = int(volume
["size"])
898 if volume
.get("image"):
899 device
["image name"] = str(volume
["image"])
900 if volume
.get("image-checksum"):
901 device
["image checksum"] = str(volume
["image-checksum"])
902 devices
.append(device
)
906 "name": get_str(vdu
, "name", 250) + "-flv",
907 "vcpus": int(vdu
["vm-flavor"].get("vcpu-count", 1)),
908 "ram": int(vdu
["vm-flavor"].get("memory-mb", 1)),
909 "disk": int(vdu
["vm-flavor"].get("storage-gb", 1)),
915 extended
["devices"] = devices
916 if vdu
.get("guest-epa"): # TODO or dedicated_int:
918 if vdu
["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int:
919 numa_node_policy
= vdu
["guest-epa"].get("numa-node-policy")
920 if numa_node_policy
.get("node"):
921 numa_node
= numa_node_policy
["node"]['0']
922 if numa_node
.get("num-cores"):
923 numa
["cores"] = numa_node
["num-cores"]
925 if numa_node
.get("paired-threads"):
926 if numa_node
["paired-threads"].get("num-paired-threads"):
927 numa
["paired-threads"] = int(numa_node
["paired-threads"]["num-paired-threads"])
929 if len(numa_node
["paired-threads"].get("paired-thread-ids")):
930 numa
["paired-threads-id"] = []
931 for pair
in numa_node
["paired-threads"]["paired-thread-ids"].itervalues():
932 numa
["paired-threads-id"].append(
933 (str(pair
["thread-a"]), str(pair
["thread-b"]))
935 if numa_node
.get("num-threads"):
936 numa
["threads"] = int(numa_node
["num-threads"])
938 if numa_node
.get("memory-mb"):
939 numa
["memory"] = max(int(numa_node
["memory-mb"] / 1024), 1)
940 if vdu
["guest-epa"].get("mempage-size"):
941 if vdu
["guest-epa"]["mempage-size"] != "SMALL":
942 numa
["memory"] = max(int(db_flavor
["ram"] / 1024), 1)
943 if vdu
["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set
:
944 if vdu
["guest-epa"]["cpu-pinning-policy"] == "DEDICATED":
945 if vdu
["guest-epa"].get("cpu-thread-pinning-policy") and \
946 vdu
["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER":
947 numa
["cores"] = max(db_flavor
["vcpus"], 1)
949 numa
["threads"] = max(db_flavor
["vcpus"], 1)
951 extended
["numas"] = [numa
]
953 extended_text
= yaml
.safe_dump(extended
, default_flow_style
=True, width
=256)
954 db_flavor
["extended"] = extended_text
955 # look if flavor exist
957 temp_flavor_dict
= {'disk': db_flavor
.get('disk', 1),
958 'ram': db_flavor
.get('ram'),
959 'vcpus': db_flavor
.get('vcpus'),
960 'extended': db_flavor
.get('extended')
962 existing_flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
964 flavor_uuid
= existing_flavors
[0]["uuid"]
966 flavor_uuid
= str(uuid4())
967 uuid_list
.append(flavor_uuid
)
968 db_flavor
["uuid"] = flavor_uuid
969 db_flavors
.append(db_flavor
)
970 db_vm
["flavor_id"] = flavor_uuid
974 if vdu
.get("cloud-init"):
975 boot_data
["user-data"] = str(vdu
["cloud-init"])
976 elif vdu
.get("cloud-init-file"):
977 # TODO Where this file content is present???
978 # boot_data["user-data"] = vnfd_yang.files[vdu["cloud-init-file"]]
979 boot_data
["user-data"] = str(vdu
["cloud-init-file"])
981 if vdu
.get("supplemental-boot-data"):
982 if vdu
["supplemental-boot-data"].get('boot-data-drive'):
983 boot_data
['boot-data-drive'] = True
984 if vdu
["supplemental-boot-data"].get('config-file'):
985 om_cfgfile_list
= list()
986 for custom_config_file
in vdu
["supplemental-boot-data"]['config-file'].itervalues():
987 # TODO Where this file content is present???
988 cfg_source
= str(custom_config_file
["source"])
989 om_cfgfile_list
.append({"dest": custom_config_file
["dest"],
990 "content": cfg_source
})
991 boot_data
['config-files'] = om_cfgfile_list
993 db_vm
["boot_data"] = yaml
.safe_dump(boot_data
, default_flow_style
=True, width
=256)
998 # table interfaces (internal/external interfaces)
999 cp_name2iface_uuid
= {}
1000 cp_name2vm_uuid
= {}
1001 # for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()):
1002 for iface
in vdu
.get("interface").itervalues():
1003 iface_uuid
= str(uuid4())
1004 uuid_list
.append(iface_uuid
)
1007 "internal_name": get_str(iface
, "name", 255),
1010 if iface
.get("virtual-interface").get("vpci"):
1011 db_interface
["vpci"] = get_str(iface
.get("virtual-interface"), "vpci", 12)
1013 if iface
.get("virtual-interface").get("bandwidth"):
1014 bps
= int(iface
.get("virtual-interface").get("bandwidth"))
1015 db_interface
["bw"] = bps
/1000
1017 if iface
.get("virtual-interface").get("type") == "OM-MGMT":
1018 db_interface
["type"] = "mgmt"
1019 elif iface
.get("virtual-interface").get("type") in ("VIRTIO", "E1000"):
1020 db_interface
["type"] = "bridge"
1021 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1022 elif iface
.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
1023 db_interface
["type"] = "data"
1024 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1026 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual"
1027 "-interface':'type':'{}'. Interface type is not supported".format(
1028 str(vnfd
["id"])[:255], str(vdu
["id"])[:255],
1029 iface
.get("virtual-interface").get("type")),
1032 if iface
.get("external-connection-point-ref"):
1034 cp
= vnfd
.get("connection-point")[iface
.get("external-connection-point-ref")]
1035 db_interface
["external_name"] = get_str(cp
, "name", 255)
1036 cp_name2iface_uuid
[db_interface
["external_name"]] = iface_uuid
1037 cp_name2vm_uuid
[db_interface
["external_name"]] = vm_uuid
1038 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1039 if cp_descriptor
["name"] == db_interface
["external_name"]:
1041 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1042 db_interface
["port_security"] = 0
1043 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1044 db_interface
["port_security"] = 1
1046 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1047 "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present"
1048 " at connection-point".format(
1049 vnf
=vnfd
["id"], vdu
=vdu
["id"], iface
=iface
["name"],
1050 cp
=iface
.get("vnfd-connection-point-ref")),
1052 elif iface
.get("internal-connection-point-ref"):
1054 for vld
in vnfd
.get("internal-vld").itervalues():
1055 for cp
in vld
.get("internal-connection-point").itervalues():
1056 if cp
.get("id-ref") == iface
.get("internal-connection-point-ref"):
1057 db_interface
["net_id"] = net_id2uuid
[vld
.get("id")]
1058 for cp_descriptor
in vnfd_descriptor
["connection-point"]:
1059 if cp_descriptor
["name"] == db_interface
["external_name"]:
1061 if str(cp_descriptor
.get("port-security-enabled")).lower() == "false":
1062 db_interface
["port_security"] = 0
1063 elif str(cp_descriptor
.get("port-security-enabled")).lower() == "true":
1064 db_interface
["port_security"] = 1
1067 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1068 "'interface[{iface}]':'vdu-internal-connection-point-ref':'{cp}' is not"
1069 " referenced by any internal-vld".format(
1070 vnf
=vnfd
["id"], vdu
=vdu
["id"], iface
=iface
["name"],
1071 cp
=iface
.get("vdu-internal-connection-point-ref")),
1073 if iface
.get("position") is not None:
1074 db_interface
["created_at"] = int(iface
.get("position")) - 1000
1075 db_interfaces
.append(db_interface
)
1077 # VNF affinity and antiaffinity
1078 for pg
in vnfd
.get("placement-groups").itervalues():
1079 pg_name
= get_str(pg
, "name", 255)
1080 for vdu
in pg
.get("member-vdus").itervalues():
1081 vdu_id
= get_str(vdu
, "member-vdu-ref", 255)
1082 if vdu_id
not in vdu_id2db_table_index
:
1083 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':"
1084 "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
1085 vnf
=vnfd
["id"], pg
=pg_name
, vdu
=vdu_id
),
1087 db_vms
[vdu_id2db_table_index
[vdu_id
]]["availability_zone"] = pg_name
1088 # TODO consider the case of isolation and not colocation
1089 # if pg.get("strategy") == "ISOLATION":
1091 # VNF mgmt configuration
1093 if vnfd
["mgmt-interface"].get("vdu-id"):
1094 if vnfd
["mgmt-interface"]["vdu-id"] not in vdu_id2uuid
:
1095 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':"
1096 "'{vdu}'. Reference to a non-existing vdu".format(
1097 vnf
=vnfd
["id"], vdu
=vnfd
["mgmt-interface"]["vdu-id"]),
1099 mgmt_access
["vm_id"] = vdu_id2uuid
[vnfd
["mgmt-interface"]["vdu-id"]]
1100 if vnfd
["mgmt-interface"].get("ip-address"):
1101 mgmt_access
["ip-address"] = str(vnfd
["mgmt-interface"].get("ip-address"))
1102 if vnfd
["mgmt-interface"].get("cp"):
1103 if vnfd
["mgmt-interface"]["cp"] not in cp_name2iface_uuid
:
1104 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp':'{cp}'. "
1105 "Reference to a non-existing connection-point".format(
1106 vnf
=vnfd
["id"], cp
=vnfd
["mgmt-interface"]["cp"]),
1108 mgmt_access
["vm_id"] = cp_name2vm_uuid
[vnfd
["mgmt-interface"]["cp"]]
1109 mgmt_access
["interface_id"] = cp_name2iface_uuid
[vnfd
["mgmt-interface"]["cp"]]
1110 default_user
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1114 mgmt_access
["default_user"] = default_user
1115 required
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1118 mgmt_access
["required"] = required
1121 db_vnf
["mgmt_access"] = yaml
.safe_dump(mgmt_access
, default_flow_style
=True, width
=256)
1125 db_vnfs
.append(db_vnf
)
1129 {"images": db_images
},
1130 {"flavors": db_flavors
},
1132 {"interfaces": db_interfaces
},
1135 logger
.debug("create_vnf Deployment done vnfDict: %s",
1136 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
1137 mydb
.new_rows(db_tables
, uuid_list
)
1138 return vnfd_uuid_list
1139 except NfvoException
:
1141 except Exception as e
:
1142 logger
.error("Exception {}".format(e
))
1143 raise # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
1146 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
1147 global global_config
1149 # Step 1. Check the VNF descriptor
1150 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
1151 # Step 2. Check tenant exist
1153 if tenant_id
!= "any":
1154 check_tenant(mydb
, tenant_id
)
1155 if "tenant_id" in vnf_descriptor
["vnf"]:
1156 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1157 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1160 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1161 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1162 if global_config
["auto_push_VNF_to_VIMs"]:
1163 vims
= get_vim(mydb
, tenant_id
)
1165 # Step 4. Review the descriptor and add missing fields
1166 #print vnf_descriptor
1167 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1168 vnf_name
= vnf_descriptor
['vnf']['name']
1169 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1170 if "physical" in vnf_descriptor
['vnf']:
1171 del vnf_descriptor
['vnf']['physical']
1172 #print vnf_descriptor
1174 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1175 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1176 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1178 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1179 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1180 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1182 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1183 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1185 VNFCitem
["name"] = vnfc
['name']
1186 VNFCitem
["availability_zone"] = vnfc
.get('availability_zone')
1187 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1189 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1192 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1193 myflavorDict
["description"] = VNFCitem
["description"]
1194 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1195 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1196 myflavorDict
["disk"] = vnfc
.get("disk", 1)
1197 myflavorDict
["extended"] = {}
1199 devices
= vnfc
.get("devices")
1201 myflavorDict
["extended"]["devices"] = devices
1204 # 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
1205 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1207 # Previous code has been commented
1208 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1209 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1210 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1211 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1213 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1215 # print "Error creating flavor: unknown processor model. Rollback successful."
1216 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1218 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1219 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1221 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1222 myflavorDict
['extended']['numas'] = vnfc
['numas']
1226 # Step 6.2 New flavors are created in the VIM
1227 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1229 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1230 VNFCitem
["flavor_id"] = flavor_id
1231 VNFCDict
[vnfc
['name']] = VNFCitem
1233 logger
.debug("Creating new images in the VIM for each VNFC")
1234 # Step 6.3 New images are created in the VIM
1235 #For each VNFC, we must create the appropriate image.
1236 #This "for" loop might be integrated with the previous one
1237 #In case this integration is made, the VNFCDict might become a VNFClist.
1238 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1239 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1241 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1242 image_dict
['universal_name']=vnfc
.get('image name')
1243 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1244 image_dict
['location']=vnfc
.get('VNFC image')
1245 #image_dict['new_location']=vnfc.get('image location')
1246 image_dict
['checksum']=vnfc
.get('image checksum')
1247 image_metadata_dict
= vnfc
.get('image metadata', None)
1248 image_metadata_str
= None
1249 if image_metadata_dict
is not None:
1250 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1251 image_dict
['metadata']=image_metadata_str
1252 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1253 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1254 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1255 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1256 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1257 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1258 if vnfc
.get("boot-data"):
1259 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1262 # Step 7. Storing the VNF descriptor in the repository
1263 if "descriptor" not in vnf_descriptor
["vnf"]:
1264 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1266 # Step 8. Adding the VNF to the NFVO DB
1267 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1269 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1270 _
, message
= rollback(mydb
, vims
, rollback_list
)
1271 if isinstance(e
, db_base_Exception
):
1272 error_text
= "Exception at database"
1273 elif isinstance(e
, KeyError):
1274 error_text
= "KeyError exception "
1275 e
.http_code
= HTTP_Internal_Server_Error
1277 error_text
= "Exception at VIM"
1278 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1279 #logger.error("start_scenario %s", error_text)
1280 raise NfvoException(error_text
, e
.http_code
)
1283 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
1284 global global_config
1286 # Step 1. Check the VNF descriptor
1287 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
1288 # Step 2. Check tenant exist
1290 if tenant_id
!= "any":
1291 check_tenant(mydb
, tenant_id
)
1292 if "tenant_id" in vnf_descriptor
["vnf"]:
1293 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1294 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1297 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1298 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1299 if global_config
["auto_push_VNF_to_VIMs"]:
1300 vims
= get_vim(mydb
, tenant_id
)
1302 # Step 4. Review the descriptor and add missing fields
1303 #print vnf_descriptor
1304 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1305 vnf_name
= vnf_descriptor
['vnf']['name']
1306 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1307 if "physical" in vnf_descriptor
['vnf']:
1308 del vnf_descriptor
['vnf']['physical']
1309 #print vnf_descriptor
1311 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1312 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1313 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1315 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1316 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1317 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1319 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1320 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1322 VNFCitem
["name"] = vnfc
['name']
1323 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1325 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1328 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1329 myflavorDict
["description"] = VNFCitem
["description"]
1330 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1331 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1332 myflavorDict
["disk"] = vnfc
.get("disk", 1)
1333 myflavorDict
["extended"] = {}
1335 devices
= vnfc
.get("devices")
1337 myflavorDict
["extended"]["devices"] = devices
1340 # 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
1341 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1343 # Previous code has been commented
1344 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1345 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1346 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1347 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1349 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1351 # print "Error creating flavor: unknown processor model. Rollback successful."
1352 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1354 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1355 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1357 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1358 myflavorDict
['extended']['numas'] = vnfc
['numas']
1362 # Step 6.2 New flavors are created in the VIM
1363 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1365 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1366 VNFCitem
["flavor_id"] = flavor_id
1367 VNFCDict
[vnfc
['name']] = VNFCitem
1369 logger
.debug("Creating new images in the VIM for each VNFC")
1370 # Step 6.3 New images are created in the VIM
1371 #For each VNFC, we must create the appropriate image.
1372 #This "for" loop might be integrated with the previous one
1373 #In case this integration is made, the VNFCDict might become a VNFClist.
1374 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1375 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1377 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1378 image_dict
['universal_name']=vnfc
.get('image name')
1379 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1380 image_dict
['location']=vnfc
.get('VNFC image')
1381 #image_dict['new_location']=vnfc.get('image location')
1382 image_dict
['checksum']=vnfc
.get('image checksum')
1383 image_metadata_dict
= vnfc
.get('image metadata', None)
1384 image_metadata_str
= None
1385 if image_metadata_dict
is not None:
1386 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1387 image_dict
['metadata']=image_metadata_str
1388 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1389 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1390 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1391 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1392 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1393 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1394 if vnfc
.get("boot-data"):
1395 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1397 # Step 7. Storing the VNF descriptor in the repository
1398 if "descriptor" not in vnf_descriptor
["vnf"]:
1399 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1401 # Step 8. Adding the VNF to the NFVO DB
1402 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1404 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1405 _
, message
= rollback(mydb
, vims
, rollback_list
)
1406 if isinstance(e
, db_base_Exception
):
1407 error_text
= "Exception at database"
1408 elif isinstance(e
, KeyError):
1409 error_text
= "KeyError exception "
1410 e
.http_code
= HTTP_Internal_Server_Error
1412 error_text
= "Exception at VIM"
1413 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1414 #logger.error("start_scenario %s", error_text)
1415 raise NfvoException(error_text
, e
.http_code
)
1418 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
1419 #check valid tenant_id
1420 check_tenant(mydb
, tenant_id
)
1423 if tenant_id
!= "any":
1424 where_or
["tenant_id"] = tenant_id
1425 where_or
["public"] = True
1426 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1428 vnf_id
= vnf
["uuid"]
1429 filter_keys
= ('uuid', 'name', 'description', 'public', "tenant_id", "osm_id", "created_at")
1430 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
1431 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1432 data
={'vnf' : filtered_content
}
1434 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1435 SELECT
=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
1437 WHERE
={'vnfs.uuid': vnf_id
} )
1439 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1440 # change boot_data into boot-data
1442 if vm
.get("boot_data"):
1443 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1446 data
['vnf']['VNFC'] = content
1447 #TODO: GET all the information from a VNFC and include it in the output.
1450 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1451 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1452 WHERE
={'vnfs.uuid': vnf_id
} )
1453 data
['vnf']['nets'] = content
1455 #GET ip-profile for each net
1456 for net
in data
['vnf']['nets']:
1457 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1458 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1459 WHERE
={'net_id': net
["uuid"]} )
1460 if len(ipprofiles
)==1:
1461 net
["ip_profile"] = ipprofiles
[0]
1462 elif len(ipprofiles
)>1:
1463 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
1466 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1468 #GET External Interfaces
1469 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1470 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1471 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1472 WHERE
={'vnfs.uuid': vnf_id
},
1473 WHERE_NOT
={'interfaces.external_name': None} )
1475 data
['vnf']['external-connections'] = content
1480 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1481 # Check tenant exist
1482 if tenant_id
!= "any":
1483 check_tenant(mydb
, tenant_id
)
1484 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1485 vims
= get_vim(mydb
, tenant_id
)
1489 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1491 if tenant_id
!= "any":
1492 where_or
["tenant_id"] = tenant_id
1493 where_or
["public"] = True
1494 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1495 vnf_id
= vnf
["uuid"]
1497 # "Getting the list of flavors and tenants of the VNF"
1498 flavorList
= get_flavorlist(mydb
, vnf_id
)
1499 if len(flavorList
)==0:
1500 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1502 imageList
= get_imagelist(mydb
, vnf_id
)
1503 if len(imageList
)==0:
1504 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1506 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1508 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1511 for flavor
in flavorList
:
1512 #check if flavor is used by other vnf
1514 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1516 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1518 #flavor not used, must be deleted
1520 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
1521 for flavor_vim
in c
:
1522 if flavor_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1524 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
1526 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
1528 myvim
.delete_flavor(flavor_vim
["vim_id"])
1529 except vimconn
.vimconnNotFoundException
as e
:
1530 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
1531 except vimconn
.vimconnException
as e
:
1532 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1533 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1534 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
1535 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1536 mydb
.delete_row_by_id('flavors', flavor
)
1537 except db_base_Exception
as e
:
1538 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1539 undeletedItems
.append("flavor %s" % flavor
)
1542 for image
in imageList
:
1544 #check if image is used by other vnf
1545 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1547 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1549 #image not used, must be deleted
1551 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1553 if image_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1555 if image_vim
['created']=='false': #skip this image because not created by openmano
1557 myvim
=vims
[ image_vim
["datacenter_id"] ]
1559 myvim
.delete_image(image_vim
["vim_id"])
1560 except vimconn
.vimconnNotFoundException
as e
:
1561 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1562 except vimconn
.vimconnException
as e
:
1563 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1564 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1565 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1566 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1567 mydb
.delete_row_by_id('images', image
)
1568 except db_base_Exception
as e
:
1569 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1570 undeletedItems
.append("image %s" % image
)
1572 return vnf_id
+ " " + vnf
["name"]
1574 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1577 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1578 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1582 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1583 myvim
= vims
.values()[0]
1584 result
,servers
= myvim
.get_hosts_info()
1586 return result
, servers
1587 topology
= {'name':myvim
['name'] , 'servers': servers
}
1588 return result
, topology
1591 def get_hosts(mydb
, nfvo_tenant_id
):
1592 vims
= get_vim(mydb
, nfvo_tenant_id
)
1594 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1596 #print "nfvo.datacenter_action() error. Several datacenters found"
1597 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1598 myvim
= vims
.values()[0]
1600 hosts
= myvim
.get_hosts()
1601 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1603 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1605 server
={'name':host
['name'], 'vms':[]}
1606 for vm
in host
['instances']:
1607 #get internal name and model
1609 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1610 WHERE
={'vim_vm_id':vm
['id']} )
1612 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1614 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1616 except db_base_Exception
as e
:
1617 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1618 datacenter
['Datacenters'][0]['servers'].append(server
)
1619 #return -400, "en construccion"
1621 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1623 except vimconn
.vimconnException
as e
:
1624 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1627 def new_scenario(mydb
, tenant_id
, topo
):
1629 # result, vims = get_vim(mydb, tenant_id)
1631 # return result, vims
1633 if tenant_id
!= "any":
1634 check_tenant(mydb
, tenant_id
)
1635 if "tenant_id" in topo
:
1636 if topo
["tenant_id"] != tenant_id
:
1637 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1642 #1.1: get VNFs and external_networks (other_nets).
1644 other_nets
={} #external_networks, bridge_networks and data_networkds
1645 nodes
= topo
['topology']['nodes']
1646 for k
in nodes
.keys():
1647 if nodes
[k
]['type'] == 'VNF':
1649 vnfs
[k
]['ifaces'] = {}
1650 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1651 other_nets
[k
] = nodes
[k
]
1652 other_nets
[k
]['external']=True
1653 elif nodes
[k
]['type'] == 'network':
1654 other_nets
[k
] = nodes
[k
]
1655 other_nets
[k
]['external']=False
1658 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1659 for name
,vnf
in vnfs
.items():
1661 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1663 error_pos
= "'topology':'nodes':'" + name
+ "'"
1665 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1666 where
['uuid'] = vnf
['vnf_id']
1667 if 'VNF model' in vnf
:
1668 error_text
+= " 'VNF model' " + vnf
['VNF model']
1669 where
['name'] = vnf
['VNF model']
1671 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1673 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1679 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1681 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1682 vnf
['uuid']=vnf_db
[0]['uuid']
1683 vnf
['description']=vnf_db
[0]['description']
1684 #get external interfaces
1685 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1686 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1687 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1688 for ext_iface
in ext_ifaces
:
1689 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1691 #1.4 get list of connections
1692 conections
= topo
['topology']['connections']
1693 conections_list
= []
1694 conections_list_name
= []
1695 for k
in conections
.keys():
1696 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1697 ifaces_list
= conections
[k
]['nodes'].items()
1698 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1700 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1701 for k2
in conection_pair_list
:
1704 con_type
= conections
[k
].get("type", "link")
1705 if con_type
!= "link":
1707 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1708 other_nets
[k
] = {'external': False}
1709 if conections
[k
].get("graph"):
1710 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1711 ifaces_list
.append( (k
, None) )
1714 if con_type
== "external_network":
1715 other_nets
[k
]['external'] = True
1716 if conections
[k
].get("model"):
1717 other_nets
[k
]["model"] = conections
[k
]["model"]
1719 other_nets
[k
]["model"] = k
1720 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1721 other_nets
[k
]["model"] = con_type
1723 conections_list_name
.append(k
)
1724 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)
1725 #print set(ifaces_list)
1726 #check valid VNF and iface names
1727 for iface
in ifaces_list
:
1728 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1729 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1730 str(k
), iface
[0]), HTTP_Not_Found
)
1731 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1732 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1733 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1735 #1.5 unify connections from the pair list to a consolidated list
1737 while index
< len(conections_list
):
1739 while index2
< len(conections_list
):
1740 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1741 conections_list
[index
] |
= conections_list
[index2
]
1742 del conections_list
[index2
]
1743 del conections_list_name
[index2
]
1746 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1748 #for k in conections_list:
1753 #1.6 Delete non external nets
1754 # for k in other_nets.keys():
1755 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1756 # for con in conections_list:
1758 # for index in range(0,len(con)):
1759 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1760 # for index in delete_indexes:
1763 #1.7: Check external_ports are present at database table datacenter_nets
1764 for k
,net
in other_nets
.items():
1765 error_pos
= "'topology':'nodes':'" + k
+ "'"
1766 if net
['external']==False:
1767 if 'name' not in net
:
1769 if 'model' not in net
:
1770 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1771 if net
['model']=='bridge_net':
1772 net
['type']='bridge';
1773 elif net
['model']=='dataplane_net':
1776 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1778 #IF we do not want to check that external network exist at datacenter
1783 # if 'net_id' in net:
1784 # error_text += " 'net_id' " + net['net_id']
1785 # WHERE_['uuid'] = net['net_id']
1786 # if 'model' in net:
1787 # error_text += " 'model' " + net['model']
1788 # WHERE_['name'] = net['model']
1789 # if len(WHERE_) == 0:
1790 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1791 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1792 # FROM='datacenter_nets', WHERE=WHERE_ )
1794 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1796 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1797 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1799 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1800 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1801 # other_nets[k].update(net_db[0])
1804 net_nb
=0 #Number of nets
1805 for con
in conections_list
:
1806 #check if this is connected to a external net
1810 for index
in range(0,len(con
)):
1811 #check if this is connected to a external net
1812 for net_key
in other_nets
.keys():
1813 if con
[index
][0]==net_key
:
1814 if other_net_index
>=0:
1815 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1816 #print "nfvo.new_scenario " + error_text
1817 raise NfvoException(error_text
, HTTP_Bad_Request
)
1819 other_net_index
= index
1820 net_target
= net_key
1822 #print "other_net_index", other_net_index
1824 if other_net_index
>=0:
1825 del con
[other_net_index
]
1826 #IF we do not want to check that external network exist at datacenter
1827 if other_nets
[net_target
]['external'] :
1828 if "name" not in other_nets
[net_target
]:
1829 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1830 if other_nets
[net_target
]["type"] == "external_network":
1831 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1832 other_nets
[net_target
]["type"] = "data"
1834 other_nets
[net_target
]["type"] = "bridge"
1836 # if other_nets[net_target]['external'] :
1837 # 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
1838 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1839 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1840 # print "nfvo.new_scenario " + error_text
1841 # return -HTTP_Bad_Request, error_text
1844 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1847 net_type_bridge
=False
1849 net_target
= "__-__net"+str(net_nb
)
1850 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1851 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1854 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1855 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1856 if iface_type
=='mgmt' or iface_type
=='bridge':
1857 net_type_bridge
= True
1859 net_type_data
= True
1860 if net_type_bridge
and net_type_data
:
1861 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1862 #print "nfvo.new_scenario " + error_text
1863 raise NfvoException(error_text
, HTTP_Bad_Request
)
1864 elif net_type_bridge
:
1867 type_
='data' if len(con
)>2 else 'ptp'
1868 net_list
[net_target
]['type'] = type_
1871 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1872 #print "nfvo.new_scenario " + error_text
1874 raise NfvoException(error_text
, HTTP_Bad_Request
)
1876 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1877 #1.8.1 obtain management net
1878 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1879 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1880 #1.8.2 check all interfaces from all vnfs
1882 add_mgmt_net
= False
1883 for vnf
in vnfs
.values():
1884 for iface
in vnf
['ifaces'].values():
1885 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1886 #iface not connected
1887 iface
['net_key'] = 'mgmt'
1889 if add_mgmt_net
and 'mgmt' not in net_list
:
1890 net_list
['mgmt']=mgmt_net
[0]
1891 net_list
['mgmt']['external']=True
1892 net_list
['mgmt']['graph']={'visible':False}
1894 net_list
.update(other_nets
)
1896 #print 'net_list', net_list
1901 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1902 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1903 'tenant_id':tenant_id
, 'name':topo
['name'],
1904 'description':topo
.get('description',topo
['name']),
1905 'public': topo
.get('public', False)
1911 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
1912 """ This creates a new scenario for version 0.2 and 0.3"""
1913 scenario
= scenario_dict
["scenario"]
1914 if tenant_id
!= "any":
1915 check_tenant(mydb
, tenant_id
)
1916 if "tenant_id" in scenario
:
1917 if scenario
["tenant_id"] != tenant_id
:
1918 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1919 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1920 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1924 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
1925 for name
,vnf
in scenario
["vnfs"].iteritems():
1927 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1929 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1931 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1932 where
['uuid'] = vnf
['vnf_id']
1933 if 'vnf_name' in vnf
:
1934 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1935 where
['name'] = vnf
['vnf_name']
1937 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1938 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
1943 if len(vnf_db
) == 0:
1944 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1945 elif len(vnf_db
) > 1:
1946 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1947 vnf
['uuid'] = vnf_db
[0]['uuid']
1948 vnf
['description'] = vnf_db
[0]['description']
1950 # get external interfaces
1951 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
1952 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1953 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name': None} )
1954 for ext_iface
in ext_ifaces
:
1955 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
1956 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1958 # 2: Insert net_key and ip_address at every vnf interface
1959 for net_name
, net
in scenario
["networks"].items():
1960 net_type_bridge
= False
1961 net_type_data
= False
1962 for iface_dict
in net
["interfaces"]:
1963 if version
== "0.2":
1964 temp_dict
= iface_dict
1966 elif version
== "0.3":
1967 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
1968 ip_address
= iface_dict
.get('ip_address', None)
1969 for vnf
, iface
in temp_dict
.items():
1970 if vnf
not in scenario
["vnfs"]:
1971 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
1973 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1974 raise NfvoException(error_text
, HTTP_Not_Found
)
1975 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1976 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
1977 .format(net_name
, iface
)
1978 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1979 raise NfvoException(error_text
, HTTP_Bad_Request
)
1980 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1981 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
1982 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1983 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1984 raise NfvoException(error_text
, HTTP_Bad_Request
)
1985 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1986 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
1987 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1988 if iface_type
== 'mgmt' or iface_type
== 'bridge':
1989 net_type_bridge
= True
1991 net_type_data
= True
1993 if net_type_bridge
and net_type_data
:
1994 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
1996 # logger.debug("nfvo.new_scenario " + error_text)
1997 raise NfvoException(error_text
, HTTP_Bad_Request
)
1998 elif net_type_bridge
:
2001 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
2003 if net
.get("implementation"): # for v0.3
2004 if type_
== "bridge" and net
["implementation"] == "underlay":
2005 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
2006 "'network':'{}'".format(net_name
)
2007 # logger.debug(error_text)
2008 raise NfvoException(error_text
, HTTP_Bad_Request
)
2009 elif type_
!= "bridge" and net
["implementation"] == "overlay":
2010 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
2011 "'network':'{}'".format(net_name
)
2012 # logger.debug(error_text)
2013 raise NfvoException(error_text
, HTTP_Bad_Request
)
2014 net
.pop("implementation")
2015 if "type" in net
and version
== "0.3": # for v0.3
2016 if type_
== "data" and net
["type"] == "e-line":
2017 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
2018 "'e-line' at 'network':'{}'".format(net_name
)
2019 # logger.debug(error_text)
2020 raise NfvoException(error_text
, HTTP_Bad_Request
)
2021 elif type_
== "ptp" and net
["type"] == "e-lan":
2025 net
['name'] = net_name
2026 net
['external'] = net
.get('external', False)
2028 # 3: insert at database
2029 scenario
["nets"] = scenario
["networks"]
2030 scenario
['tenant_id'] = tenant_id
2031 scenario_id
= mydb
.new_scenario(scenario
)
2035 def new_nsd_v3(mydb
, tenant_id
, nsd_descriptor
):
2037 Parses an OSM IM nsd_catalog and insert at DB
2040 :param nsd_descriptor:
2041 :return: The list of cretated NSD ids
2044 mynsd
= nsd_catalog
.nsd()
2046 pybindJSONDecoder
.load_ietf_json(nsd_descriptor
, None, None, obj
=mynsd
)
2047 except Exception as e
:
2048 raise NfvoException("Error. Invalid NS descriptor format: " + str(e
), HTTP_Bad_Request
)
2052 db_sce_interfaces
= []
2054 db_ip_profiles_index
= 0
2057 for nsd_yang
in mynsd
.nsd_catalog
.nsd
.itervalues():
2058 nsd
= nsd_yang
.get()
2061 scenario_uuid
= str(uuid4())
2062 uuid_list
.append(scenario_uuid
)
2063 nsd_uuid_list
.append(scenario_uuid
)
2065 "uuid": scenario_uuid
,
2066 "osm_id": get_str(nsd
, "id", 255),
2067 "name": get_str(nsd
, "name", 255),
2068 "description": get_str(nsd
, "description", 255),
2069 "tenant_id": tenant_id
,
2070 "vendor": get_str(nsd
, "vendor", 255),
2071 "short_name": get_str(nsd
, "short-name", 255),
2072 "descriptor": str(nsd_descriptor
)[:60000],
2074 db_scenarios
.append(db_scenario
)
2076 # table sce_vnfs (constituent-vnfd)
2077 vnf_index2scevnf_uuid
= {}
2078 vnf_index2vnf_uuid
= {}
2079 for vnf
in nsd
.get("constituent-vnfd").itervalues():
2080 existing_vnf
= mydb
.get_rows(FROM
="vnfs", WHERE
={'osm_id': str(vnf
["vnfd-id-ref"])[:255],
2081 'tenant_id': tenant_id
})
2082 if not existing_vnf
:
2083 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':"
2084 "'{}'. Reference to a non-existing VNFD in the catalog".format(
2085 str(nsd
["id"]), str(vnf
["vnfd-id-ref"])[:255]),
2087 sce_vnf_uuid
= str(uuid4())
2088 uuid_list
.append(sce_vnf_uuid
)
2090 "uuid": sce_vnf_uuid
,
2091 "scenario_id": scenario_uuid
,
2092 "name": existing_vnf
[0]["name"][:200] + "." + get_str(vnf
, "member-vnf-index", 5),
2093 "vnf_id": existing_vnf
[0]["uuid"],
2094 "member_vnf_index": int(vnf
["member-vnf-index"]),
2095 # TODO 'start-by-default': True
2097 vnf_index2scevnf_uuid
[int(vnf
['member-vnf-index'])] = sce_vnf_uuid
2098 vnf_index2vnf_uuid
[int(vnf
['member-vnf-index'])] = existing_vnf
[0]["uuid"]
2099 db_sce_vnfs
.append(db_sce_vnf
)
2101 # table ip_profiles (ip-profiles)
2102 ip_profile_name2db_table_index
= {}
2103 for ip_profile
in nsd
.get("ip-profiles").itervalues():
2105 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
2106 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
2107 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
2108 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
2109 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
2110 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
2113 for dns
in ip_profile
["ip-profile-params"]["dns-server"].itervalues():
2114 dns_list
.append(str(dns
.get("address")))
2115 db_ip_profile
["dns_address"] = ";".join(dns_list
)
2116 if ip_profile
["ip-profile-params"].get('security-group'):
2117 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
2118 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
2119 db_ip_profiles_index
+= 1
2120 db_ip_profiles
.append(db_ip_profile
)
2122 # table sce_nets (internal-vld)
2123 for vld
in nsd
.get("vld").itervalues():
2124 sce_net_uuid
= str(uuid4())
2125 uuid_list
.append(sce_net_uuid
)
2127 "uuid": sce_net_uuid
,
2128 "name": get_str(vld
, "name", 255),
2129 "scenario_id": scenario_uuid
,
2131 "multipoint": not vld
.get("type") == "ELINE",
2133 "description": get_str(vld
, "description", 255),
2135 # guess type of network
2136 if vld
.get("mgmt-network"):
2137 db_sce_net
["type"] = "bridge"
2138 db_sce_net
["external"] = True
2139 elif vld
.get("provider-network").get("overlay-type") == "VLAN":
2140 db_sce_net
["type"] = "data"
2142 db_sce_net
["type"] = "bridge"
2143 db_sce_nets
.append(db_sce_net
)
2145 # ip-profile, link db_ip_profile with db_sce_net
2146 if vld
.get("ip-profile-ref"):
2147 ip_profile_name
= vld
.get("ip-profile-ref")
2148 if ip_profile_name
not in ip_profile_name2db_table_index
:
2149 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}'."
2150 " Reference to a non-existing 'ip_profiles'".format(
2151 str(nsd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
2153 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["sce_net_id"] = sce_net_uuid
2155 # table sce_interfaces (vld:vnfd-connection-point-ref)
2156 for iface
in vld
.get("vnfd-connection-point-ref").itervalues():
2157 vnf_index
= int(iface
['member-vnf-index-ref'])
2158 # check correct parameters
2159 if vnf_index
not in vnf_index2vnf_uuid
:
2160 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2161 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2162 "'nsd':'constituent-vnfd'".format(
2163 str(nsd
["id"]), str(vld
["id"]), str(iface
["member-vnf-index-ref"])),
2166 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2167 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2168 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2169 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2171 if not existing_ifaces
:
2172 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2173 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2174 "connection-point name at VNFD '{}'".format(
2175 str(nsd
["id"]), str(vld
["id"]), str(iface
["vnfd-connection-point-ref"]),
2176 str(iface
.get("vnfd-id-ref"))[:255]),
2178 interface_uuid
= existing_ifaces
[0]["uuid"]
2179 sce_interface_uuid
= str(uuid4())
2180 uuid_list
.append(sce_net_uuid
)
2181 db_sce_interface
= {
2182 "uuid": sce_interface_uuid
,
2183 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2184 "sce_net_id": sce_net_uuid
,
2185 "interface_id": interface_uuid
,
2186 # "ip_address": #TODO
2188 db_sce_interfaces
.append(db_sce_interface
)
2191 {"scenarios": db_scenarios
},
2192 {"sce_nets": db_sce_nets
},
2193 {"ip_profiles": db_ip_profiles
},
2194 {"sce_vnfs": db_sce_vnfs
},
2195 {"sce_interfaces": db_sce_interfaces
},
2198 logger
.debug("create_vnf Deployment done vnfDict: %s",
2199 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2200 mydb
.new_rows(db_tables
, uuid_list
)
2201 return nsd_uuid_list
2202 except NfvoException
:
2204 except Exception as e
:
2205 logger
.error("Exception {}".format(e
))
2206 raise # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
2209 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
2210 data
["uuid"] = scenario_id
2211 data
["tenant_id"] = tenant_id
2212 c
= mydb
.edit_scenario( data
)
2216 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
2217 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2218 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
2219 vims
= {datacenter_id
: myvim
}
2220 myvim_tenant
= myvim
['tenant_id']
2221 datacenter_name
= myvim
['name']
2225 #print "Checking that the scenario_id exists and getting the scenario dictionary"
2226 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
=datacenter_id
)
2227 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
2228 scenarioDict
['datacenter_id'] = datacenter_id
2229 #print '================scenarioDict======================='
2230 #print json.dumps(scenarioDict, indent=4)
2231 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
2233 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
2234 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2236 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2237 auxNetDict
['scenario'] = {}
2239 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
2240 for sce_net
in scenarioDict
['nets']:
2241 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
2243 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
2244 myNetName
= myNetName
[0:255] #limit length
2245 myNetType
= sce_net
['type']
2247 myNetDict
["name"] = myNetName
2248 myNetDict
["type"] = myNetType
2249 myNetDict
["tenant_id"] = myvim_tenant
2250 myNetIPProfile
= sce_net
.get('ip_profile', None)
2252 #We should use the dictionary as input parameter for new_network
2254 if not sce_net
["external"]:
2255 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2256 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2257 sce_net
['vim_id'] = network_id
2258 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2259 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2260 sce_net
["created"] = True
2262 if sce_net
['vim_id'] == None:
2263 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
2264 _
, message
= rollback(mydb
, vims
, rollbackList
)
2265 logger
.error("nfvo.start_scenario: %s", error_text
)
2266 raise NfvoException(error_text
, HTTP_Bad_Request
)
2267 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2268 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2270 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2271 #For each vnf net, we create it and we add it to instanceNetlist.
2273 for sce_vnf
in scenarioDict
['vnfs']:
2274 for net
in sce_vnf
['nets']:
2275 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2277 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
2278 myNetName
= myNetName
[0:255] #limit length
2279 myNetType
= net
['type']
2281 myNetDict
["name"] = myNetName
2282 myNetDict
["type"] = myNetType
2283 myNetDict
["tenant_id"] = myvim_tenant
2284 myNetIPProfile
= net
.get('ip_profile', None)
2287 #We should use the dictionary as input parameter for new_network
2288 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2289 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2290 net
['vim_id'] = network_id
2291 if sce_vnf
['uuid'] not in auxNetDict
:
2292 auxNetDict
[sce_vnf
['uuid']] = {}
2293 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2294 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2295 net
["created"] = True
2297 #print "auxNetDict:"
2298 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2300 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2301 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2303 for sce_vnf
in scenarioDict
['vnfs']:
2304 vnf_availability_zones
= []
2305 for vm
in sce_vnf
['vms']:
2306 vm_av
= vm
.get('availability_zone')
2307 if vm_av
and vm_av
not in vnf_availability_zones
:
2308 vnf_availability_zones
.append(vm_av
)
2310 # check if there is enough availability zones available at vim level.
2311 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2312 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2313 raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request
)
2315 for vm
in sce_vnf
['vms']:
2318 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2319 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2320 #myVMDict['description'] = vm['description']
2321 myVMDict
['description'] = myVMDict
['name'][0:99]
2323 myVMDict
['start'] = "no"
2324 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2325 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2327 #create image at vim in case it not exist
2328 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2329 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2330 vm
['vim_image_id'] = image_id
2332 #create flavor at vim in case it not exist
2333 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2334 if flavor_dict
['extended']!=None:
2335 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2336 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2337 vm
['vim_flavor_id'] = flavor_id
2340 myVMDict
['imageRef'] = vm
['vim_image_id']
2341 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2342 myVMDict
['networks'] = []
2343 for iface
in vm
['interfaces']:
2345 if iface
['type']=="data":
2346 netDict
['type'] = iface
['model']
2347 elif "model" in iface
and iface
["model"]!=None:
2348 netDict
['model']=iface
['model']
2349 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2350 #discover type of interface looking at flavor
2351 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2352 for flavor_iface
in numa
.get('interfaces',[]):
2353 if flavor_iface
.get('name') == iface
['internal_name']:
2354 if flavor_iface
['dedicated'] == 'yes':
2355 netDict
['type']="PF" #passthrough
2356 elif flavor_iface
['dedicated'] == 'no':
2357 netDict
['type']="VF" #siov
2358 elif flavor_iface
['dedicated'] == 'yes:sriov':
2359 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2360 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2362 netDict
["use"]=iface
['type']
2363 if netDict
["use"]=="data" and not netDict
.get("type"):
2364 #print "netDict", netDict
2365 #print "iface", iface
2366 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'])
2367 if flavor_dict
.get('extended')==None:
2368 raise NfvoException(e_text
+ "After database migration some information is not available. \
2369 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2371 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2372 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2373 netDict
["type"]="virtual"
2374 if "vpci" in iface
and iface
["vpci"] is not None:
2375 netDict
['vpci'] = iface
['vpci']
2376 if "mac" in iface
and iface
["mac"] is not None:
2377 netDict
['mac_address'] = iface
['mac']
2378 if "port-security" in iface
and iface
["port-security"] is not None:
2379 netDict
['port_security'] = iface
['port-security']
2380 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2381 netDict
['floating_ip'] = iface
['floating-ip']
2382 netDict
['name'] = iface
['internal_name']
2383 if iface
['net_id'] is None:
2384 for vnf_iface
in sce_vnf
["interfaces"]:
2387 if vnf_iface
['interface_id']==iface
['uuid']:
2388 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2391 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2392 #skip bridge ifaces not connected to any net
2393 #if 'net_id' not in netDict or netDict['net_id']==None:
2395 myVMDict
['networks'].append(netDict
)
2396 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2397 #print myVMDict['name']
2398 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2399 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2400 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2402 if 'availability_zone' in myVMDict
:
2403 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2407 vm_id
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2408 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2409 availability_zone_index
=av_index
,
2410 availability_zone_list
=vnf_availability_zones
)
2411 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2412 vm
['vim_id'] = vm_id
2413 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2414 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2415 for net
in myVMDict
['networks']:
2417 for iface
in vm
['interfaces']:
2418 if net
["name"]==iface
["internal_name"]:
2419 iface
["vim_id"]=net
["vim_id"]
2422 logger
.debug("start scenario Deployment done")
2423 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2424 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2425 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2426 return mydb
.get_instance_scenario(instance_id
)
2428 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2429 _
, message
= rollback(mydb
, vims
, rollbackList
)
2430 if isinstance(e
, db_base_Exception
):
2431 error_text
= "Exception at database"
2433 error_text
= "Exception at VIM"
2434 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2435 #logger.error("start_scenario %s", error_text)
2436 raise NfvoException(error_text
, e
.http_code
)
2438 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2439 """ join the cloud config information into cloud_config_preserve.
2440 In case of conflict cloud_config_preserve preserves
2443 if not cloud_config_preserve
and not cloud_config
:
2446 new_cloud_config
= {"key-pairs":[], "users":[]}
2448 if cloud_config_preserve
:
2449 for key
in cloud_config_preserve
.get("key-pairs", () ):
2450 if key
not in new_cloud_config
["key-pairs"]:
2451 new_cloud_config
["key-pairs"].append(key
)
2453 for key
in cloud_config
.get("key-pairs", () ):
2454 if key
not in new_cloud_config
["key-pairs"]:
2455 new_cloud_config
["key-pairs"].append(key
)
2456 if not new_cloud_config
["key-pairs"]:
2457 del new_cloud_config
["key-pairs"]
2461 new_cloud_config
["users"] += cloud_config
.get("users", () )
2462 if cloud_config_preserve
:
2463 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2464 index_to_delete
= []
2465 users
= new_cloud_config
.get("users", [])
2466 for index0
in range(0,len(users
)):
2467 if index0
in index_to_delete
:
2469 for index1
in range(index0
+1,len(users
)):
2470 if index1
in index_to_delete
:
2472 if users
[index0
]["name"] == users
[index1
]["name"]:
2473 index_to_delete
.append(index1
)
2474 for key
in users
[index1
].get("key-pairs",()):
2475 if "key-pairs" not in users
[index0
]:
2476 users
[index0
]["key-pairs"] = [key
]
2477 elif key
not in users
[index0
]["key-pairs"]:
2478 users
[index0
]["key-pairs"].append(key
)
2479 index_to_delete
.sort(reverse
=True)
2480 for index
in index_to_delete
:
2482 if not new_cloud_config
["users"]:
2483 del new_cloud_config
["users"]
2486 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2487 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2488 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2489 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2492 new_cloud_config
["user-data"] = []
2493 if cloud_config
and cloud_config
.get("user-data"):
2494 if isinstance(cloud_config
["user-data"], list):
2495 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2497 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2498 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2499 if isinstance(cloud_config_preserve
["user-data"], list):
2500 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2502 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2503 if not new_cloud_config
["user-data"]:
2504 del new_cloud_config
["user-data"]
2507 new_cloud_config
["config-files"] = []
2508 if cloud_config
and cloud_config
.get("config-files") != None:
2509 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2510 if cloud_config_preserve
:
2511 for file in cloud_config_preserve
.get("config-files", ()):
2512 for index
in range(0, len(new_cloud_config
["config-files"])):
2513 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2514 new_cloud_config
["config-files"][index
] = file
2517 new_cloud_config
["config-files"].append(file)
2518 if not new_cloud_config
["config-files"]:
2519 del new_cloud_config
["config-files"]
2520 return new_cloud_config
2523 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2524 datacenter_id
= None
2525 datacenter_name
= None
2528 if datacenter_tenant_id
:
2529 thread_id
= datacenter_tenant_id
2530 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2532 where_
={"td.nfvo_tenant_id": tenant_id
}
2533 if datacenter_id_name
:
2534 if utils
.check_valid_uuid(datacenter_id_name
):
2535 datacenter_id
= datacenter_id_name
2536 where_
["dt.datacenter_id"] = datacenter_id
2538 datacenter_name
= datacenter_id_name
2539 where_
["d.name"] = datacenter_name
2540 if datacenter_tenant_id
:
2541 where_
["dt.uuid"] = datacenter_tenant_id
2542 datacenters
= mydb
.get_rows(
2543 SELECT
=("dt.uuid as datacenter_tenant_id",),
2544 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2545 "join datacenters as d on d.uuid=dt.datacenter_id",
2547 if len(datacenters
) > 1:
2548 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2550 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2551 thread
= vim_threads
["running"].get(thread_id
)
2553 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2554 return thread_id
, thread
2555 except db_base_Exception
as e
:
2556 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2559 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2561 if utils
.check_valid_uuid(datacenter_id_name
):
2562 WHERE_dict
['d.uuid'] = datacenter_id_name
2564 WHERE_dict
['d.name'] = datacenter_id_name
2567 WHERE_dict
['nfvo_tenant_id'] = tenant_id
2568 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
2569 " dt on td.datacenter_tenant_id=dt.uuid"
2571 from_
= 'datacenters as d'
2572 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid",), WHERE
=WHERE_dict
)
2573 if len(vimaccounts
) == 0:
2574 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2575 elif len(vimaccounts
)>1:
2576 #print "nfvo.datacenter_action() error. Several datacenters found"
2577 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2578 return vimaccounts
[0]["uuid"]
2581 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
2582 datacenter_id
= None
2583 datacenter_name
= None
2584 if datacenter_id_name
:
2585 if utils
.check_valid_uuid(datacenter_id_name
):
2586 datacenter_id
= datacenter_id_name
2588 datacenter_name
= datacenter_id_name
2589 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
2591 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2593 #print "nfvo.datacenter_action() error. Several datacenters found"
2594 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2595 return vims
.keys()[0], vims
.values()[0]
2599 '''Takes dict d and updates it with the values in dict u.'''
2600 '''It merges all depth levels'''
2601 for k
, v
in u
.iteritems():
2602 if isinstance(v
, collections
.Mapping
):
2603 r
= update(d
.get(k
, {}), v
)
2609 def create_instance(mydb
, tenant_id
, instance_dict
):
2610 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2611 # logger.debug("Creating instance...")
2612 scenario
= instance_dict
["scenario"]
2614 # find main datacenter
2616 myvim_threads_id
= {}
2617 datacenter
= instance_dict
.get("datacenter")
2618 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2619 myvims
[default_datacenter_id
] = vim
2620 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
2621 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
2622 # myvim_tenant = myvim['tenant_id']
2626 # print "Checking that the scenario exists and getting the scenario dictionary"
2627 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
2628 datacenter_id
=default_datacenter_id
)
2630 # logger.debug(">>>>>> Dictionaries before merging")
2631 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
2632 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
2634 db_instance_vnfs
= []
2635 db_instance_vms
= []
2636 db_instance_interfaces
= []
2641 instance_name
= instance_dict
["name"]
2642 instance_uuid
= str(uuid4())
2643 uuid_list
.append(instance_uuid
)
2644 db_instance_scenario
= {
2645 "uuid": instance_uuid
,
2646 "name": instance_name
,
2647 "tenant_id": tenant_id
,
2648 "scenario_id": scenarioDict
['uuid'],
2649 "datacenter_id": default_datacenter_id
,
2650 # filled bellow 'datacenter_tenant_id'
2651 "description": instance_dict
.get("description"),
2653 if scenarioDict
.get("cloud-config"):
2654 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
2655 default_flow_style
=True, width
=256)
2656 instance_action_id
= get_task_id()
2657 db_instance_action
= {
2658 "uuid": instance_action_id
, # same uuid for the instance and the action on create
2659 "tenant_id": tenant_id
,
2660 "instance_id": instance_uuid
,
2661 "description": "CREATE",
2664 # Auxiliary dictionaries from x to y
2665 vnf_net2instance
= {}
2666 sce_net2instance
= {}
2667 net2task_id
= {'scenario': {}}
2669 # logger.debug("Creating instance from scenario-dict:\n%s",
2670 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
2672 # 0 check correct parameters
2673 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
2675 for scenario_net
in scenarioDict
['nets']:
2676 if net_name
== scenario_net
["name"]:
2680 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
),
2682 if "sites" not in net_instance_desc
:
2683 net_instance_desc
["sites"] = [ {} ]
2684 site_without_datacenter_field
= False
2685 for site
in net_instance_desc
["sites"]:
2686 if site
.get("datacenter"):
2687 site
["datacenter"] = get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
2688 if site
["datacenter"] not in myvims
:
2689 # Add this datacenter to myvims
2690 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
2692 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
2693 site
["datacenter"] = d
# change name to id
2695 if site_without_datacenter_field
:
2696 raise NfvoException("Found more than one entries without datacenter field at "
2697 "instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
2698 site_without_datacenter_field
= True
2699 site
["datacenter"] = default_datacenter_id
# change name to id
2701 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
2703 for scenario_vnf
in scenarioDict
['vnfs']:
2704 if vnf_name
== scenario_vnf
['name']:
2708 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
2709 if "datacenter" in vnf_instance_desc
:
2710 # Add this datacenter to myvims
2711 vnf_instance_desc
["datacenter"] = get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2712 if vnf_instance_desc
["datacenter"] not in myvims
:
2713 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2715 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2716 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2718 # 0.1 parse cloud-config parameters
2719 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2720 # We add the RO key to cloud_config
2721 if tenant
[0].get('RO_pub_key'):
2722 RO_key
= {"key-pairs": [tenant
[0]['RO_pub_key']]}
2723 cloud_config
= unify_cloud_config(cloud_config
, RO_key
)
2725 # 0.2 merge instance information into scenario
2726 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2727 # However, this is not possible yet.
2728 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2729 for scenario_net
in scenarioDict
['nets']:
2730 if net_name
== scenario_net
["name"]:
2731 if 'ip-profile' in net_instance_desc
:
2732 # translate from input format to database format
2733 ipprofile_in
= net_instance_desc
['ip-profile']
2735 ipprofile_db
['subnet_address'] = ipprofile_in
.get('subnet-address')
2736 ipprofile_db
['ip_version'] = ipprofile_in
.get('ip-version', 'IPv4')
2737 ipprofile_db
['gateway_address'] = ipprofile_in
.get('gateway-address')
2738 ipprofile_db
['dns_address'] = ipprofile_in
.get('dns-address')
2739 if isinstance(ipprofile_db
['dns_address'], (list, tuple)):
2740 ipprofile_db
['dns_address'] = ";".join(ipprofile_db
['dns_address'])
2741 if 'dhcp' in ipprofile_in
:
2742 ipprofile_db
['dhcp_start_address'] = ipprofile_in
['dhcp'].get('start-address')
2743 ipprofile_db
['dhcp_enabled'] = ipprofile_in
['dhcp'].get('enabled', True)
2744 ipprofile_db
['dhcp_count'] = ipprofile_in
['dhcp'].get('count' )
2745 if 'ip_profile' not in scenario_net
:
2746 scenario_net
['ip_profile'] = ipprofile_db
2748 update(scenario_net
['ip_profile'], ipprofile_db
)
2749 for interface
in net_instance_desc
.get('interfaces', () ):
2750 if 'ip_address' in interface
:
2751 for vnf
in scenarioDict
['vnfs']:
2752 if interface
['vnf'] == vnf
['name']:
2753 for vnf_interface
in vnf
['interfaces']:
2754 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2755 vnf_interface
['ip_address']=interface
['ip_address']
2757 # logger.debug(">>>>>>>> Merged dictionary")
2758 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
2759 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
2761 # 1. Creating new nets (sce_nets) in the VIM"
2762 db_instance_nets
= []
2763 for sce_net
in scenarioDict
['nets']:
2764 descriptor_net
= instance_dict
.get("networks", {}).get(sce_net
["name"], {})
2765 net_name
= descriptor_net
.get("vim-network-name")
2766 sce_net2instance
[sce_net
['uuid']] = {}
2767 net2task_id
['scenario'][sce_net
['uuid']] = {}
2769 sites
= descriptor_net
.get("sites", [ {} ])
2771 if site
.get("datacenter"):
2772 vim
= myvims
[ site
["datacenter"] ]
2773 datacenter_id
= site
["datacenter"]
2774 myvim_thread_id
= myvim_threads_id
[ site
["datacenter"] ]
2776 vim
= myvims
[ default_datacenter_id
]
2777 datacenter_id
= default_datacenter_id
2778 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2779 net_type
= sce_net
['type']
2780 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
2783 if sce_net
["external"]:
2784 net_name
= sce_net
["name"]
2786 net_name
= "{}.{}".format(instance_name
, sce_net
["name"])
2787 net_name
= net_name
[:255] # limit length
2789 if "netmap-use" in site
or "netmap-create" in site
:
2790 create_network
= False
2791 lookfor_network
= False
2792 if "netmap-use" in site
:
2793 lookfor_network
= True
2794 if utils
.check_valid_uuid(site
["netmap-use"]):
2795 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2796 lookfor_filter
["id"] = site
["netmap-use"]
2798 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2799 lookfor_filter
["name"] = site
["netmap-use"]
2800 if "netmap-create" in site
:
2801 create_network
= True
2802 net_vim_name
= net_name
2803 if site
["netmap-create"]:
2804 net_vim_name
= site
["netmap-create"]
2805 elif sce_net
["external"]:
2806 if sce_net
['vim_id'] != None:
2807 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
2808 create_network
= False
2809 lookfor_network
= True
2810 lookfor_filter
["id"] = sce_net
['vim_id']
2811 filter_text
= "vim_id '{}' datacenter_netmap name '{}'. Try to reload vims with "\
2812 "datacenter-net-update".format(sce_net
['vim_id'], sce_net
["name"])
2813 # look for network at datacenter and return error
2815 # There is not a netmap, look at datacenter for a net with this name and create if not found
2816 create_network
= True
2817 lookfor_network
= True
2818 lookfor_filter
["name"] = sce_net
["name"]
2819 net_vim_name
= sce_net
["name"]
2820 filter_text
= "scenario name '%s'" % sce_net
["name"]
2822 net_vim_name
= net_name
2823 create_network
= True
2824 lookfor_network
= False
2826 if lookfor_network
and create_network
:
2827 # TODO create two tasks FIND + CREATE with their relationship
2828 task_action
= "FIND"
2829 task_params
= (lookfor_filter
,)
2830 # task_action = "CREATE"
2831 # task_params = (net_vim_name, net_type, sce_net.get('ip_profile', None))
2833 elif lookfor_network
:
2834 task_action
= "FIND"
2835 task_params
= (lookfor_filter
,)
2836 elif create_network
:
2837 task_action
= "CREATE"
2838 task_params
= (net_vim_name
, net_type
, sce_net
.get('ip_profile', None))
2840 # fill database content
2841 net_uuid
= str(uuid4())
2842 uuid_list
.append(net_uuid
)
2843 sce_net2instance
[sce_net
['uuid']][datacenter_id
] = net_uuid
2847 "instance_scenario_id": instance_uuid
,
2848 "sce_net_id": sce_net
["uuid"],
2849 "created": create_network
,
2850 'datacenter_id': datacenter_id
,
2851 'datacenter_tenant_id': myvim_thread_id
,
2852 'status': 'BUILD' if create_network
else "ACTIVE"
2854 db_instance_nets
.append(db_net
)
2856 "instance_action_id": instance_action_id
,
2857 "status": "SCHEDULED",
2858 "task_index": task_index
,
2859 "datacenter_vim_id": myvim_thread_id
,
2860 "action": task_action
,
2861 "item": "instance_nets",
2862 "item_id": net_uuid
,
2863 "extra": yaml
.safe_dump({"params": task_params
}, default_flow_style
=True, width
=256)
2865 net2task_id
['scenario'][sce_net
['uuid']][datacenter_id
] = task_index
2867 db_vim_actions
.append(db_vim_action
)
2869 if 'ip_profile' in sce_net
:
2871 'instance_net_id': net_uuid
,
2872 'ip_version': sce_net
['ip_profile']['ip_version'],
2873 'subnet_address': sce_net
['ip_profile']['subnet_address'],
2874 'gateway_address': sce_net
['ip_profile']['gateway_address'],
2875 'dns_address': sce_net
['ip_profile']['dns_address'],
2876 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
2877 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
2878 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
2880 db_ip_profiles
.append(db_ip_profile
)
2882 # 2. Creating new nets (vnf internal nets) in the VIM"
2883 # For each vnf net, we create it and we add it to instanceNetlist.
2884 for sce_vnf
in scenarioDict
['vnfs']:
2885 for net
in sce_vnf
['nets']:
2886 if sce_vnf
.get("datacenter"):
2887 datacenter_id
= sce_vnf
["datacenter"]
2888 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
2890 datacenter_id
= default_datacenter_id
2891 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2892 descriptor_net
= instance_dict
.get("vnfs", {}).get(sce_vnf
["name"], {})
2893 net_name
= descriptor_net
.get("name")
2895 net_name
= "{}.{}".format(instance_name
, net
["name"])
2896 net_name
= net_name
[:255] # limit length
2897 net_type
= net
['type']
2899 if sce_vnf
['uuid'] not in vnf_net2instance
:
2900 vnf_net2instance
[sce_vnf
['uuid']] = {}
2901 if sce_vnf
['uuid'] not in net2task_id
:
2902 net2task_id
[sce_vnf
['uuid']] = {}
2903 net2task_id
[sce_vnf
['uuid']][net
['uuid']] = task_index
2905 # fill database content
2906 net_uuid
= str(uuid4())
2907 uuid_list
.append(net_uuid
)
2908 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
2912 "instance_scenario_id": instance_uuid
,
2913 "net_id": net
["uuid"],
2915 'datacenter_id': datacenter_id
,
2916 'datacenter_tenant_id': myvim_thread_id
,
2918 db_instance_nets
.append(db_net
)
2921 "instance_action_id": instance_action_id
,
2922 "task_index": task_index
,
2923 "datacenter_vim_id": myvim_thread_id
,
2924 "status": "SCHEDULED",
2926 "item": "instance_nets",
2927 "item_id": net_uuid
,
2928 "extra": yaml
.safe_dump({"params": (net_name
, net_type
, net
.get('ip_profile',None))},
2929 default_flow_style
=True, width
=256)
2932 db_vim_actions
.append(db_vim_action
)
2934 if 'ip_profile' in net
:
2936 'instance_net_id': net_uuid
,
2937 'ip_version': net
['ip_profile']['ip_version'],
2938 'subnet_address': net
['ip_profile']['subnet_address'],
2939 'gateway_address': net
['ip_profile']['gateway_address'],
2940 'dns_address': net
['ip_profile']['dns_address'],
2941 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
2942 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
2943 'dhcp_count': net
['ip_profile']['dhcp_count'],
2945 db_ip_profiles
.append(db_ip_profile
)
2947 # print "vnf_net2instance:"
2948 # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
2950 # 3. Creating new vm instances in the VIM
2951 # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2952 sce_vnf_list
= sorted(scenarioDict
['vnfs'], key
=lambda k
: k
['name'])
2953 for sce_vnf
in sce_vnf_list
:
2954 vnf_availability_zones
= []
2955 for vm
in sce_vnf
['vms']:
2956 vm_av
= vm
.get('availability_zone')
2957 if vm_av
and vm_av
not in vnf_availability_zones
:
2958 vnf_availability_zones
.append(vm_av
)
2960 # check if there is enough availability zones available at vim level.
2961 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2962 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2963 raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request
)
2965 if sce_vnf
.get("datacenter"):
2966 vim
= myvims
[ sce_vnf
["datacenter"] ]
2967 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"] ]
2968 datacenter_id
= sce_vnf
["datacenter"]
2970 vim
= myvims
[ default_datacenter_id
]
2971 myvim_thread_id
= myvim_threads_id
[ default_datacenter_id
]
2972 datacenter_id
= default_datacenter_id
2973 sce_vnf
["datacenter_id"] = datacenter_id
2976 vnf_uuid
= str(uuid4())
2977 uuid_list
.append(vnf_uuid
)
2980 'instance_scenario_id': instance_uuid
,
2981 'vnf_id': sce_vnf
['vnf_id'],
2982 'sce_vnf_id': sce_vnf
['uuid'],
2983 'datacenter_id': datacenter_id
,
2984 'datacenter_tenant_id': myvim_thread_id
,
2986 db_instance_vnfs
.append(db_instance_vnf
)
2988 for vm
in sce_vnf
['vms']:
2990 myVMDict
['name'] = "{}.{}.{}".format(instance_name
[:64], sce_vnf
['name'][:64], vm
["name"][:64])
2991 myVMDict
['description'] = myVMDict
['name'][0:99]
2993 # myVMDict['start'] = "no"
2994 myVMDict
['name'] = myVMDict
['name'][0:255] # limit name length
2995 #create image at vim in case it not exist
2996 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2997 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2998 vm
['vim_image_id'] = image_id
3000 # create flavor at vim in case it not exist
3001 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
3002 if flavor_dict
['extended']!=None:
3003 flavor_dict
['extended'] = yaml
.load(flavor_dict
['extended'])
3004 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
3006 # Obtain information for additional disks
3007 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
3008 if not extended_flavor_dict
:
3009 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
3012 # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
3013 myVMDict
['disks'] = None
3014 extended_info
= extended_flavor_dict
[0]['extended']
3015 if extended_info
!= None:
3016 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
3017 if 'disks' in extended_flavor_dict_yaml
:
3018 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
3020 vm
['vim_flavor_id'] = flavor_id
3021 myVMDict
['imageRef'] = vm
['vim_image_id']
3022 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
3023 myVMDict
['availability_zone'] = vm
.get('availability_zone')
3024 myVMDict
['networks'] = []
3025 task_depends_on
= []
3026 # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
3028 for iface
in vm
['interfaces']:
3030 if iface
['type']=="data":
3031 netDict
['type'] = iface
['model']
3032 elif "model" in iface
and iface
["model"]!=None:
3033 netDict
['model']=iface
['model']
3034 # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
3035 # is obtained from iterface table model
3036 # discover type of interface looking at flavor
3037 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
3038 for flavor_iface
in numa
.get('interfaces',[]):
3039 if flavor_iface
.get('name') == iface
['internal_name']:
3040 if flavor_iface
['dedicated'] == 'yes':
3041 netDict
['type']="PF" #passthrough
3042 elif flavor_iface
['dedicated'] == 'no':
3043 netDict
['type']="VF" #siov
3044 elif flavor_iface
['dedicated'] == 'yes:sriov':
3045 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
3046 netDict
["mac_address"] = flavor_iface
.get("mac_address")
3048 netDict
["use"]=iface
['type']
3049 if netDict
["use"]=="data" and not netDict
.get("type"):
3050 #print "netDict", netDict
3051 #print "iface", iface
3052 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'])
3053 if flavor_dict
.get('extended')==None:
3054 raise NfvoException(e_text
+ "After database migration some information is not available. \
3055 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
3057 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
3058 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
3059 netDict
["type"]="virtual"
3060 if "vpci" in iface
and iface
["vpci"] is not None:
3061 netDict
['vpci'] = iface
['vpci']
3062 if "mac" in iface
and iface
["mac"] is not None:
3063 netDict
['mac_address'] = iface
['mac']
3064 if "port-security" in iface
and iface
["port-security"] is not None:
3065 netDict
['port_security'] = iface
['port-security']
3066 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
3067 netDict
['floating_ip'] = iface
['floating-ip']
3068 netDict
['name'] = iface
['internal_name']
3069 if iface
['net_id'] is None:
3070 for vnf_iface
in sce_vnf
["interfaces"]:
3073 if vnf_iface
['interface_id']==iface
['uuid']:
3074 netDict
['net_id'] = "TASK-{}".format(net2task_id
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
])
3075 instance_net_id
= sce_net2instance
[ vnf_iface
['sce_net_id'] ][datacenter_id
]
3076 task_depends_on
.append(net2task_id
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
])
3079 netDict
['net_id'] = "TASK-{}".format(net2task_id
[ sce_vnf
['uuid'] ][ iface
['net_id'] ])
3080 instance_net_id
= vnf_net2instance
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
3081 task_depends_on
.append(net2task_id
[sce_vnf
['uuid'] ][ iface
['net_id']])
3082 # skip bridge ifaces not connected to any net
3083 if 'net_id' not in netDict
or netDict
['net_id']==None:
3085 myVMDict
['networks'].append(netDict
)
3088 # 'instance_vm_id': instance_vm_uuid,
3089 "instance_net_id": instance_net_id
,
3090 'interface_id': iface
['uuid'],
3091 # 'vim_interface_id': ,
3092 'type': 'external' if iface
['external_name'] is not None else 'internal',
3093 'ip_address': iface
.get('ip_address'),
3094 'floating_ip': int(iface
.get('floating-ip', False)),
3095 'port_security': int(iface
.get('port-security', True))
3097 db_vm_ifaces
.append(db_vm_iface
)
3098 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3099 # print myVMDict['name']
3100 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
3101 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
3102 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3103 if vm
.get("boot_data"):
3104 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
3106 cloud_config_vm
= cloud_config
3107 if myVMDict
.get('availability_zone'):
3108 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
3111 for vm_index
in range(0, vm
.get('count', 1)):
3113 if vm
.get('count', 1) > 1:
3114 vm_index_name
+= "." + chr(97 + vm_index
)
3115 task_params
= (myVMDict
['name']+vm_index_name
, myVMDict
['description'], myVMDict
.get('start', None),
3116 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'], cloud_config_vm
,
3117 myVMDict
['disks'], av_index
, vnf_availability_zones
)
3118 # put interface uuid back to scenario[vnfs][vms[[interfaces]
3119 for net
in myVMDict
['networks']:
3121 for iface
in vm
['interfaces']:
3122 if net
["name"]==iface
["internal_name"]:
3123 iface
["vim_id"]=net
["vim_id"]
3125 vm_uuid
= str(uuid4())
3126 uuid_list
.append(vm_uuid
)
3129 'instance_vnf_id': vnf_uuid
,
3130 #TODO delete "vim_vm_id": vm_id,
3131 "vm_id": vm
["uuid"],
3134 db_instance_vms
.append(db_vm
)
3137 for db_vm_iface
in db_vm_ifaces
:
3138 iface_uuid
= str(uuid4())
3139 uuid_list
.append(iface_uuid
)
3140 db_vm_iface_instance
= {
3142 "instance_vm_id": vm_uuid
3144 db_vm_iface_instance
.update(db_vm_iface
)
3145 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
3146 ip
= db_vm_iface_instance
.get("ip_address")
3151 ip
= ip
[i
:] + str(int(ip
[:i
]) +1)
3152 db_vm_iface_instance
["ip_address"] = ip
3154 db_vm_iface_instance
["ip_address"] = None
3155 db_instance_interfaces
.append(db_vm_iface_instance
)
3156 myVMDict
['networks'][iface_index
]["uuid"] = iface_uuid
3160 "instance_action_id": instance_action_id
,
3161 "task_index": task_index
,
3162 "datacenter_vim_id": myvim_thread_id
,
3164 "status": "SCHEDULED",
3165 "item": "instance_vms",
3167 "extra": yaml
.safe_dump({"params": task_params
, "depends_on": task_depends_on
},
3168 default_flow_style
=True, width
=256)
3171 db_vim_actions
.append(db_vim_action
)
3173 scenarioDict
["datacenter2tenant"] = myvim_threads_id
3175 db_instance_action
["number_tasks"] = task_index
3176 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
3177 db_instance_scenario
['datacenter_id'] = default_datacenter_id
3179 {"instance_scenarios": db_instance_scenario
},
3180 {"instance_vnfs": db_instance_vnfs
},
3181 {"instance_nets": db_instance_nets
},
3182 {"ip_profiles": db_ip_profiles
},
3183 {"instance_vms": db_instance_vms
},
3184 {"instance_interfaces": db_instance_interfaces
},
3185 {"instance_actions": db_instance_action
},
3186 {"vim_actions": db_vim_actions
}
3189 logger
.debug("create_instance done DB tables: %s",
3190 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
3191 mydb
.new_rows(db_tables
, uuid_list
)
3192 for myvim_thread_id
in myvim_threads_id
.values():
3193 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3195 returned_instance
= mydb
.get_instance_scenario(instance_uuid
)
3196 returned_instance
["action_id"] = instance_action_id
3197 return returned_instance
3198 except (NfvoException
, vimconn
.vimconnException
, db_base_Exception
) as e
:
3199 message
= rollback(mydb
, myvims
, rollbackList
)
3200 if isinstance(e
, db_base_Exception
):
3201 error_text
= "database Exception"
3202 elif isinstance(e
, vimconn
.vimconnException
):
3203 error_text
= "VIM Exception"
3205 error_text
= "Exception"
3206 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
3207 # logger.error("create_instance: %s", error_text)
3208 raise NfvoException(error_text
, e
.http_code
)
3211 def delete_instance(mydb
, tenant_id
, instance_id
):
3212 # print "Checking that the instance_id exists and getting the instance dictionary"
3213 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
3214 # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
3215 tenant_id
= instanceDict
["tenant_id"]
3216 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3218 # 1. Delete from Database
3219 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
3221 # 2. delete from VIM
3225 vimthread_affected
= {}
3228 instance_action_id
= get_task_id()
3230 db_instance_action
= {
3231 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3232 "tenant_id": tenant_id
,
3233 "instance_id": instance_id
,
3234 "description": "DELETE",
3235 # "number_tasks": 0 # filled bellow
3240 for sce_vnf
in instanceDict
['vnfs']:
3241 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3242 vimthread_affected
[sce_vnf
["datacenter_tenant_id"]] = None
3243 if datacenter_key
not in myvims
:
3245 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3246 except NfvoException
as e
:
3247 logger
.error(str(e
))
3249 myvim_threads
[datacenter_key
] = myvim_thread
3250 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
3251 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
3253 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
3254 sce_vnf
["datacenter_tenant_id"]))
3255 myvims
[datacenter_key
] = None
3257 myvims
[datacenter_key
] = vims
.values()[0]
3258 myvim
= myvims
[datacenter_key
]
3259 myvim_thread
= myvim_threads
[datacenter_key
]
3260 for vm
in sce_vnf
['vms']:
3262 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
3266 "instance_action_id": instance_action_id
,
3267 "task_index": task_index
,
3268 "datacenter_vim_id": sce_vnf
["datacenter_tenant_id"],
3270 "status": "SCHEDULED",
3271 "item": "instance_vms",
3272 "item_id": vm
["uuid"],
3273 "extra": yaml
.safe_dump({"params": vm
["interfaces"]},
3274 default_flow_style
=True, width
=256)
3277 db_vim_actions
.append(db_vim_action
)
3279 except vimconn
.vimconnNotFoundException
as e
:
3280 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
3281 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
3282 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
3283 except vimconn
.vimconnException
as e
:
3284 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
3285 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
3286 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
3290 for net
in instanceDict
['nets']:
3291 # TODO if not net['created']:
3292 # TODO continue #skip not created nets
3294 vimthread_affected
[net
["datacenter_tenant_id"]] = None
3295 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
3296 if datacenter_key
not in myvims
:
3298 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3299 except NfvoException
as e
:
3300 logger
.error(str(e
))
3302 myvim_threads
[datacenter_key
] = myvim_thread
3303 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
3304 datacenter_tenant_id
=net
["datacenter_tenant_id"])
3306 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
3307 myvims
[datacenter_key
] = None
3309 myvims
[datacenter_key
] = vims
.values()[0]
3310 myvim
= myvims
[datacenter_key
]
3311 myvim_thread
= myvim_threads
[datacenter_key
]
3314 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
3318 "instance_action_id": instance_action_id
,
3319 "task_index": task_index
,
3320 "datacenter_vim_id": net
["datacenter_tenant_id"],
3322 "status": "SCHEDULED",
3323 "item": "instance_nets",
3324 "item_id": net
["uuid"],
3325 "extra": yaml
.safe_dump({"params": (net
['vim_net_id'], net
['sdn_net_id'])},
3326 default_flow_style
=True, width
=256)
3329 db_vim_actions
.append(db_vim_action
)
3331 except vimconn
.vimconnNotFoundException
as e
:
3332 error_msg
+= "\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
3333 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
3334 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
3335 except vimconn
.vimconnException
as e
:
3336 error_msg
+= "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'],
3337 net
["datacenter_id"],
3338 e
.http_code
, str(e
))
3339 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
3340 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
3342 db_instance_action
["number_tasks"] = task_index
3344 {"instance_actions": db_instance_action
},
3345 {"vim_actions": db_vim_actions
}
3348 logger
.debug("delete_instance done DB tables: %s",
3349 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
3350 mydb
.new_rows(db_tables
, ())
3351 for myvim_thread_id
in vimthread_affected
.keys():
3352 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3354 if len(error_msg
) > 0:
3355 return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
3356 '(error: 404) from VIM: {}'.format(instance_action_id
, message
, error_msg
)
3358 return "action_id={} instance {} deleted".format(instance_action_id
, message
)
3361 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
3362 '''Refreshes a scenario instance. It modifies instanceDict'''
3364 - 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
3367 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
3368 # #print "nfvo.refresh_instance begins"
3369 # #print json.dumps(instanceDict, indent=4)
3371 # #print "Getting the VIM URL and the VIM tenant_id"
3374 # # 1. Getting VIM vm and net list
3375 # vms_updated = [] #List of VM instance uuids in openmano that were updated
3378 # for sce_vnf in instanceDict['vnfs']:
3379 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
3380 # if datacenter_key not in vm_list:
3381 # vm_list[datacenter_key] = []
3382 # if datacenter_key not in myvims:
3383 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
3384 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
3385 # if len(vims) == 0:
3386 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
3387 # myvims[datacenter_key] = None
3389 # myvims[datacenter_key] = vims.values()[0]
3390 # for vm in sce_vnf['vms']:
3391 # vm_list[datacenter_key].append(vm['vim_vm_id'])
3392 # vms_notupdated.append(vm["uuid"])
3394 # nets_updated = [] #List of VM instance uuids in openmano that were updated
3395 # nets_notupdated=[]
3397 # for net in instanceDict['nets']:
3398 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
3399 # if datacenter_key not in net_list:
3400 # net_list[datacenter_key] = []
3401 # if datacenter_key not in myvims:
3402 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
3403 # datacenter_tenant_id=net["datacenter_tenant_id"])
3404 # if len(vims) == 0:
3405 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
3406 # myvims[datacenter_key] = None
3408 # myvims[datacenter_key] = vims.values()[0]
3410 # net_list[datacenter_key].append(net['vim_net_id'])
3411 # nets_notupdated.append(net["uuid"])
3413 # # 1. Getting the status of all VMs
3415 # for datacenter_key in myvims:
3416 # if not vm_list.get(datacenter_key):
3420 # if not myvims[datacenter_key]:
3421 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
3424 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
3426 # except vimconn.vimconnException as e:
3427 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
3428 # failed_message = str(e)
3430 # for vm in vm_list[datacenter_key]:
3431 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
3433 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
3434 # for sce_vnf in instanceDict['vnfs']:
3435 # for vm in sce_vnf['vms']:
3436 # vm_id = vm['vim_vm_id']
3437 # interfaces = vm_dict[vm_id].pop('interfaces', [])
3438 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
3439 # has_mgmt_iface = False
3440 # for iface in vm["interfaces"]:
3441 # if iface["type"]=="mgmt":
3442 # has_mgmt_iface = True
3443 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
3444 # vm_dict[vm_id]['status'] = "ACTIVE"
3445 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
3446 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
3447 # 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'):
3448 # vm['status'] = vm_dict[vm_id]['status']
3449 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
3450 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
3451 # # 2.1. Update in openmano DB the VMs whose status changed
3453 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
3454 # vms_notupdated.remove(vm["uuid"])
3456 # vms_updated.append(vm["uuid"])
3457 # except db_base_Exception as e:
3458 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
3459 # # 2.2. Update in openmano DB the interface VMs
3460 # for interface in interfaces:
3461 # #translate from vim_net_id to instance_net_id
3462 # network_id_list=[]
3463 # for net in instanceDict['nets']:
3464 # if net["vim_net_id"] == interface["vim_net_id"]:
3465 # network_id_list.append(net["uuid"])
3466 # if not network_id_list:
3468 # del interface["vim_net_id"]
3470 # for network_id in network_id_list:
3471 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
3472 # except db_base_Exception as e:
3473 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
3475 # # 3. Getting the status of all nets
3477 # for datacenter_key in myvims:
3478 # if not net_list.get(datacenter_key):
3481 # failed_message = ""
3482 # if not myvims[datacenter_key]:
3483 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
3486 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
3488 # except vimconn.vimconnException as e:
3489 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
3490 # failed_message = str(e)
3492 # for net in net_list[datacenter_key]:
3493 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
3495 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
3496 # # TODO: update nets inside a vnf
3497 # for net in instanceDict['nets']:
3498 # net_id = net['vim_net_id']
3499 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
3500 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
3501 # 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'):
3502 # net['status'] = net_dict[net_id]['status']
3503 # net['error_msg'] = net_dict[net_id].get('error_msg')
3504 # net['vim_info'] = net_dict[net_id].get('vim_info')
3505 # # 5.1. Update in openmano DB the nets whose status changed
3507 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
3508 # nets_notupdated.remove(net["uuid"])
3510 # nets_updated.append(net["uuid"])
3511 # except db_base_Exception as e:
3512 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
3514 # # Returns appropriate output
3515 # #print "nfvo.refresh_instance finishes"
3516 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
3517 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
3518 instance_id
= instanceDict
['uuid']
3519 # if len(vms_notupdated)+len(nets_notupdated)>0:
3520 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
3521 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
3523 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
3525 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
3526 #print "Checking that the instance_id exists and getting the instance dictionary"
3527 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
3528 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
3530 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3531 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
3533 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
3534 myvim
= vims
.values()[0]
3536 if action_dict
.get("create-vdu"):
3537 for vdu
in action_dict
["create-vdu"]:
3538 vdu_id
= vdu
.get("vdu-id")
3539 vdu_count
= vdu
.get("count", 1)
3540 # get from database TODO
3544 input_vnfs
= action_dict
.pop("vnfs", [])
3545 input_vms
= action_dict
.pop("vms", [])
3546 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
3550 for sce_vnf
in instanceDict
['vnfs']:
3551 for vm
in sce_vnf
['vms']:
3552 if not action_over_all
:
3553 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
3554 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
3557 if "add_public_key" in action_dict
:
3559 if sce_vnf
.get('mgmt_access'):
3560 mgmt_access
= yaml
.load(sce_vnf
['mgmt_access'])
3561 ssh_access
= mgmt_access
['config-access']['ssh-access']
3562 tenant
= mydb
.get_rows_by_id('nfvo_tenants', nfvo_tenant
)
3564 if ssh_access
['required'] and ssh_access
['default-user']:
3565 if 'ip_address' in vm
:
3566 mgmt_ip
= vm
['ip_address'].split(';')
3567 password
= mgmt_access
['config-access'].get('password')
3568 priv_RO_key
= decrypt_key(tenant
[0]['encrypted_RO_priv_key'], tenant
[0]['uuid'])
3569 myvim
.inject_user_key(mgmt_ip
[0], ssh_access
['default-user'],
3570 action_dict
['add_public_key'],
3571 password
=password
, ro_key
=priv_RO_key
)
3573 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
3574 HTTP_Internal_Server_Error
)
3576 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
3577 HTTP_Internal_Server_Error
)
3579 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
3580 HTTP_Internal_Server_Error
)
3582 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
3583 if "console" in action_dict
:
3584 if not global_config
["http_console_proxy"]:
3585 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
3586 "description": "{protocol}//{ip}:{port}/{suffix}".format(
3587 protocol
=data
["protocol"],
3588 ip
= data
["server"],
3589 port
= data
["port"],
3590 suffix
= data
["suffix"]),
3594 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
3595 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
3596 "description": "this console is only reachable by local interface",
3601 #print "console data", data
3603 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
3604 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
3605 "description": "{protocol}//{ip}:{port}/{suffix}".format(
3606 protocol
=data
["protocol"],
3607 ip
= global_config
["http_console_host"],
3608 port
= console_thread
.port
,
3609 suffix
= data
["suffix"]),
3613 except NfvoException
as e
:
3614 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
3618 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
3620 except vimconn
.vimconnException
as e
:
3621 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
3624 if vm_ok
==0: #all goes wrong
3629 def instance_action_get(mydb
, nfvo_tenant
, instance_id
, action_id
):
3631 if nfvo_tenant
and nfvo_tenant
!= "any":
3632 filter["tenant_id"] = nfvo_tenant
3633 if instance_id
and instance_id
!= "any":
3634 filter["instance_id"] = instance_id
3636 filter["uuid"] = action_id
3637 rows
= mydb
.get_rows(FROM
="instance_actions", WHERE
=filter)
3638 if not rows
and action_id
:
3639 raise NfvoException("Not found any action with this criteria", HTTP_Not_Found
)
3640 return {"ations": rows
}
3643 def create_or_use_console_proxy_thread(console_server
, console_port
):
3644 #look for a non-used port
3645 console_thread_key
= console_server
+ ":" + str(console_port
)
3646 if console_thread_key
in global_config
["console_thread"]:
3647 #global_config["console_thread"][console_thread_key].start_timeout()
3648 return global_config
["console_thread"][console_thread_key
]
3650 for port
in global_config
["console_port_iterator"]():
3651 #print "create_or_use_console_proxy_thread() port:", port
3652 if port
in global_config
["console_ports"]:
3655 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
3657 global_config
["console_thread"][console_thread_key
] = clithread
3658 global_config
["console_ports"][port
] = console_thread_key
3660 except cli
.ConsoleProxyExceptionPortUsed
as e
:
3661 #port used, try with onoher
3663 except cli
.ConsoleProxyException
as e
:
3664 raise NfvoException(str(e
), HTTP_Bad_Request
)
3665 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
3668 def check_tenant(mydb
, tenant_id
):
3669 '''check that tenant exists at database'''
3670 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
3672 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
3675 def new_tenant(mydb
, tenant_dict
):
3677 tenant_uuid
= str(uuid4())
3678 tenant_dict
['uuid'] = tenant_uuid
3680 pub_key
, priv_key
= create_RO_keypair(tenant_uuid
)
3681 tenant_dict
['RO_pub_key'] = pub_key
3682 tenant_dict
['encrypted_RO_priv_key'] = priv_key
3683 mydb
.new_row("nfvo_tenants", tenant_dict
, confidential_data
=True)
3684 except db_base_Exception
as e
:
3685 raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict
['name']) + str(e
), HTTP_Internal_Server_Error
)
3688 def delete_tenant(mydb
, tenant
):
3689 #get nfvo_tenant info
3691 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
3692 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
3693 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
3696 def new_datacenter(mydb
, datacenter_descriptor
):
3697 if "config" in datacenter_descriptor
:
3698 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
3699 #Check that datacenter-type is correct
3700 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
3703 module
= "vimconn_" + datacenter_type
3704 pkg
= __import__("osm_ro." + module
)
3705 vim_conn
= getattr(pkg
, module
)
3706 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
3707 except (IOError, ImportError):
3708 # if module_info and module_info[0]:
3709 # file.close(module_info[0])
3710 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
3712 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True, confidential_data
=True)
3713 return datacenter_id
3716 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
3717 # obtain data, check that only one exist
3718 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
3721 datacenter_id
= datacenter
['uuid']
3722 where
={'uuid': datacenter
['uuid']}
3723 remove_port_mapping
= False
3724 if "config" in datacenter_descriptor
:
3725 if datacenter_descriptor
['config'] != None:
3727 new_config_dict
= datacenter_descriptor
["config"]
3730 for k
in new_config_dict
:
3731 if new_config_dict
[k
] == None:
3733 if k
== 'sdn-controller':
3734 remove_port_mapping
= True
3736 config_text
= datacenter
.get("config")
3739 config_dict
= yaml
.load(config_text
)
3740 config_dict
.update(new_config_dict
)
3744 except Exception as e
:
3745 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
3747 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
3749 datacenter_descriptor
["config"] = None
3750 if remove_port_mapping
:
3752 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
3753 except ovimException
as e
:
3754 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
3756 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
3757 return datacenter_id
3760 def delete_datacenter(mydb
, datacenter
):
3761 #get nfvo_tenant info
3762 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
3763 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
3765 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
3766 except ovimException
as e
:
3767 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
3768 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
3771 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):
3772 # get datacenter info
3773 datacenter_id
= get_datacenter_uuid(mydb
, None, datacenter
)
3775 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
3777 # get nfvo_tenant info
3778 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
3779 if vim_tenant_name
==None:
3780 vim_tenant_name
=tenant_dict
['name']
3782 #check that this association does not exist before
3783 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
3784 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3785 if len(tenants_datacenters
)>0:
3786 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
3788 vim_tenant_id_exist_atdb
=False
3789 if not create_vim_tenant
:
3790 where_
={"datacenter_id": datacenter_id
}
3791 if vim_tenant_id
!=None:
3792 where_
["vim_tenant_id"] = vim_tenant_id
3793 if vim_tenant_name
!=None:
3794 where_
["vim_tenant_name"] = vim_tenant_name
3795 #check if vim_tenant_id is already at database
3796 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
3797 if len(datacenter_tenants_dict
)>=1:
3798 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
3799 vim_tenant_id_exist_atdb
=True
3800 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
3802 datacenter_tenants_dict
= {}
3803 #insert at table datacenter_tenants
3804 else: #if vim_tenant_id==None:
3805 #create tenant at VIM if not provided
3807 _
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
,
3808 vim_passwd
=vim_password
)
3809 datacenter_name
= myvim
["name"]
3810 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
3811 except vimconn
.vimconnException
as e
:
3812 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
3813 datacenter_tenants_dict
= {}
3814 datacenter_tenants_dict
["created"]="true"
3816 #fill datacenter_tenants table
3817 if not vim_tenant_id_exist_atdb
:
3818 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
3819 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
3820 datacenter_tenants_dict
["user"] = vim_username
3821 datacenter_tenants_dict
["passwd"] = vim_password
3822 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
3824 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
3825 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True, confidential_data
=True)
3826 datacenter_tenants_dict
["uuid"] = id_
3828 #fill tenants_datacenters table
3829 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
3830 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
3831 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
3833 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
3834 datacenter_name
= myvim
["name"]
3835 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
3836 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
3837 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
3839 thread_id
= datacenter_tenants_dict
["uuid"]
3840 vim_threads
["running"][thread_id
] = new_thread
3841 return datacenter_id
3844 def edit_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=None, vim_tenant_name
=None,
3845 vim_username
=None, vim_password
=None, config
=None):
3846 #Obtain the data of this datacenter_tenant_id
3847 vim_data
= mydb
.get_rows(
3848 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
3849 "datacenter_tenants.passwd", "datacenter_tenants.config"),
3850 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
3851 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
3852 "tenants_datacenters.datacenter_id": datacenter_id
})
3854 logger
.debug(str(vim_data
))
3855 if len(vim_data
) < 1:
3856 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
3860 v
['config'] = yaml
.load(v
['config'])
3863 v
['vim_tenant_id'] = vim_tenant_id
3865 v
['vim_tenant_name'] = vim_tenant_name
3867 v
['user'] = vim_username
3869 v
['passwd'] = vim_password
3873 v
['config'].update(config
)
3875 logger
.debug(str(v
))
3876 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
3877 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
3878 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
3880 return datacenter_id
3882 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
3883 #get datacenter info
3884 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3886 #get nfvo_tenant info
3887 if not tenant_id
or tenant_id
=="any":
3890 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
3891 tenant_uuid
= tenant_dict
['uuid']
3893 #check that this association exist before
3894 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
3896 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
3897 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3898 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
3899 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
3901 #delete this association
3902 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3904 #get vim_tenant info and deletes
3906 for tenant_datacenter_item
in tenant_datacenter_list
:
3907 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
3908 #try to delete vim:tenant
3910 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
3911 if vim_tenant_dict
['created']=='true':
3912 #delete tenant at VIM if created by NFVO
3914 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
3915 except vimconn
.vimconnException
as e
:
3916 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
3917 logger
.warn(warning
)
3918 except db_base_Exception
as e
:
3919 logger
.error("Cannot delete datacenter_tenants " + str(e
))
3920 pass # the error will be caused because dependencies, vim_tenant can not be deleted
3921 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
3922 thread
= vim_threads
["running"][thread_id
]
3923 thread
.insert_task("exit")
3924 vim_threads
["deleting"][thread_id
] = thread
3925 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
3928 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
3930 #get datacenter info
3931 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3933 if 'net-update' in action_dict
:
3935 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
3937 except vimconn
.vimconnException
as e
:
3938 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
3939 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3940 #update nets Change from VIM format to NFVO format
3943 net_nfvo
={'datacenter_id': datacenter_id
}
3944 net_nfvo
['name'] = net
['name']
3945 #net_nfvo['description']= net['name']
3946 net_nfvo
['vim_net_id'] = net
['id']
3947 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3948 net_nfvo
['shared'] = net
['shared']
3949 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3950 net_list
.append(net_nfvo
)
3951 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
3952 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
3954 elif 'net-edit' in action_dict
:
3955 net
= action_dict
['net-edit'].pop('net')
3956 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3957 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
3958 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3960 elif 'net-delete' in action_dict
:
3961 net
= action_dict
['net-deelte'].get('net')
3962 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3963 result
= mydb
.delete_row(FROM
='datacenter_nets',
3964 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3968 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
3971 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
3972 #get datacenter info
3973 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3975 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
3976 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
3977 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
3981 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
3982 #get datacenter info
3983 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3986 action_dict
= action_dict
["netmap"]
3987 if 'vim_id' in action_dict
:
3988 filter_dict
["id"] = action_dict
['vim_id']
3989 if 'vim_name' in action_dict
:
3990 filter_dict
["name"] = action_dict
['vim_name']
3992 filter_dict
["shared"] = True
3995 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
3996 except vimconn
.vimconnException
as e
:
3997 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
3998 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3999 if len(vim_nets
)>1 and action_dict
:
4000 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
4001 elif len(vim_nets
)==0: # and action_dict:
4002 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
4004 for net
in vim_nets
:
4005 net_nfvo
={'datacenter_id': datacenter_id
}
4006 if action_dict
and "name" in action_dict
:
4007 net_nfvo
['name'] = action_dict
['name']
4009 net_nfvo
['name'] = net
['name']
4010 #net_nfvo['description']= net['name']
4011 net_nfvo
['vim_net_id'] = net
['id']
4012 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
4013 net_nfvo
['shared'] = net
['shared']
4014 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
4016 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
4017 net_nfvo
["status"] = "OK"
4018 net_nfvo
["uuid"] = net_id
4019 except db_base_Exception
as e
:
4023 net_nfvo
["status"] = "FAIL: " + str(e
)
4024 net_list
.append(net_nfvo
)
4027 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
4028 # obtain all network data
4030 if utils
.check_valid_uuid(network_id
):
4031 filter_dict
= {"id": network_id
}
4033 filter_dict
= {"name": network_id
}
4035 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4036 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
4037 except vimconn
.vimconnException
as e
:
4038 raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e
)), e
.http_code
)
4040 # ensure the network is defined
4041 if len(network
) == 0:
4042 raise NfvoException("Network {} is not present in the system".format(network_id
),
4045 # ensure there is only one network with the provided name
4046 if len(network
) > 1:
4047 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), HTTP_Bad_Request
)
4049 # ensure it is a dataplane network
4050 if network
[0]['type'] != 'data':
4053 # ensure we use the id
4054 network_id
= network
[0]['id']
4056 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
4057 # and with instance_scenario_id==NULL
4058 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
4059 search_dict
= {'vim_net_id': network_id
}
4062 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
4063 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
4064 except db_base_Exception
as e
:
4065 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
4066 network_id
) + str(e
), HTTP_Internal_Server_Error
)
4070 if net
['sdn_net_id'] != None:
4072 sdn_net_id
= net
['sdn_net_id']
4074 if sdn_net_counter
== 0:
4076 elif sdn_net_counter
== 1:
4079 raise NfvoException("More than one SDN network is associated to vim network {}".format(
4080 network_id
), HTTP_Internal_Server_Error
)
4082 def get_sdn_controller_id(mydb
, datacenter
):
4083 # Obtain sdn controller id
4084 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
4088 return yaml
.load(config
).get('sdn-controller')
4090 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
4092 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
4093 if not sdn_network_id
:
4094 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), HTTP_Internal_Server_Error
)
4096 #Obtain sdn controller id
4097 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
4098 if not controller_id
:
4099 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), HTTP_Internal_Server_Error
)
4101 #Obtain sdn controller info
4102 sdn_controller
= ovim
.show_of_controller(controller_id
)
4105 'name': 'external_port',
4106 'net_id': sdn_network_id
,
4107 'ofc_id': controller_id
,
4108 'switch_dpid': sdn_controller
['dpid'],
4109 'switch_port': descriptor
['port']
4112 if 'vlan' in descriptor
:
4113 port_data
['vlan'] = descriptor
['vlan']
4114 if 'mac' in descriptor
:
4115 port_data
['mac'] = descriptor
['mac']
4117 result
= ovim
.new_port(port_data
)
4118 except ovimException
as e
:
4119 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
4120 sdn_network_id
, network_id
) + str(e
), HTTP_Internal_Server_Error
)
4121 except db_base_Exception
as e
:
4122 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
4123 network_id
) + str(e
), HTTP_Internal_Server_Error
)
4125 return 'Port uuid: '+ result
4127 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
4129 filter = {'uuid': port_id
}
4131 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
4132 if not sdn_network_id
:
4133 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
4134 HTTP_Internal_Server_Error
)
4135 #in case no port_id is specified only ports marked as 'external_port' will be detached
4136 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
4139 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
4140 except ovimException
as e
:
4141 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
4142 HTTP_Internal_Server_Error
)
4144 if len(port_list
) == 0:
4145 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
4149 for port
in port_list
:
4151 port_uuid_list
.append(port
['uuid'])
4152 ovim
.delete_port(port
['uuid'])
4153 except ovimException
as e
:
4154 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), HTTP_Internal_Server_Error
)
4156 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
4158 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
4159 #get datacenter info
4160 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4163 if utils
.check_valid_uuid(name
):
4164 filter_dict
["id"] = name
4166 filter_dict
["name"] = name
4168 if item
=="networks":
4169 #filter_dict['tenant_id'] = myvim['tenant_id']
4170 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
4172 if len(content
) == 0:
4173 raise NfvoException("Network {} is not present in the system. ".format(name
),
4176 #Update the networks with the attached ports
4178 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
4179 if sdn_network_id
!= None:
4181 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
4182 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
4183 except ovimException
as e
:
4184 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), HTTP_Internal_Server_Error
)
4185 #Remove field name and if port name is external_port save it as 'type'
4186 for port
in port_list
:
4187 if port
['name'] == 'external_port':
4188 port
['type'] = "External"
4190 net
['sdn_network_id'] = sdn_network_id
4191 net
['sdn_attached_ports'] = port_list
4193 elif item
=="tenants":
4194 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
4195 elif item
== "images":
4197 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
4199 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4200 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
4201 if name
and len(content
)==1:
4202 return {item
[:-1]: content
[0]}
4203 elif name
and len(content
)==0:
4204 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
4207 return {item
: content
}
4208 except vimconn
.vimconnException
as e
:
4209 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
4210 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
4213 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
4214 #get datacenter info
4215 if tenant_id
== "any":
4218 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4220 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
4221 logger
.debug("vim_action_delete vim response: " + str(content
))
4222 items
= content
.values()[0]
4223 if type(items
)==list and len(items
)==0:
4224 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
4225 elif type(items
)==list and len(items
)>1:
4226 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
4227 else: # it is a dict
4228 item_id
= items
["id"]
4229 item_name
= str(items
.get("name"))
4232 if item
=="networks":
4233 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
4234 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
4235 if sdn_network_id
!= None:
4236 #Delete any port attachment to this network
4238 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
4239 except ovimException
as e
:
4240 raise NfvoException(
4241 "ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
4242 HTTP_Internal_Server_Error
)
4244 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
4245 for port
in port_list
:
4246 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
4248 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
4250 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id
, 'vim_net_id': item_id
})
4251 except db_base_Exception
as e
:
4252 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
4253 str(e
), HTTP_Internal_Server_Error
)
4255 #Delete the SDN network
4257 ovim
.delete_network(sdn_network_id
)
4258 except ovimException
as e
:
4259 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
4260 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
4261 HTTP_Internal_Server_Error
)
4263 content
= myvim
.delete_network(item_id
)
4264 elif item
=="tenants":
4265 content
= myvim
.delete_tenant(item_id
)
4266 elif item
== "images":
4267 content
= myvim
.delete_image(item_id
)
4269 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4270 except vimconn
.vimconnException
as e
:
4271 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
4272 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
4274 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
4277 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
4278 #get datacenter info
4279 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
4280 if tenant_id
== "any":
4282 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4284 if item
=="networks":
4285 net
= descriptor
["network"]
4286 net_name
= net
.pop("name")
4287 net_type
= net
.pop("type", "bridge")
4288 net_public
= net
.pop("shared", False)
4289 net_ipprofile
= net
.pop("ip_profile", None)
4290 net_vlan
= net
.pop("vlan", None)
4291 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
4293 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
4294 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
4297 sdn_network
['vlan'] = net_vlan
4298 sdn_network
['type'] = net_type
4299 sdn_network
['name'] = net_name
4300 ovim_content
= ovim
.new_network(sdn_network
)
4301 except ovimException
as e
:
4302 self
.logger
.error("ovimException creating SDN network={} ".format(
4303 sdn_network
) + str(e
), exc_info
=True)
4304 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
4305 HTTP_Internal_Server_Error
)
4307 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
4308 # use instance_scenario_id=None to distinguish from real instaces of nets
4309 correspondence
= {'instance_scenario_id': None, 'sdn_net_id': ovim_content
, 'vim_net_id': content
}
4310 #obtain datacenter_tenant_id
4311 correspondence
['datacenter_tenant_id'] = mydb
.get_rows(SELECT
=('uuid',), FROM
='datacenter_tenants', WHERE
={'datacenter_id': datacenter
})[0]['uuid']
4314 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
4315 except db_base_Exception
as e
:
4316 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
4317 str(e
), HTTP_Internal_Server_Error
)
4318 elif item
=="tenants":
4319 tenant
= descriptor
["tenant"]
4320 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
4322 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4323 except vimconn
.vimconnException
as e
:
4324 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
4326 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
4328 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
4329 data
= ovim
.new_of_controller(sdn_controller
)
4330 logger
.debug('New SDN controller created with uuid {}'.format(data
))
4333 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
4334 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
4335 msg
= 'SDN controller {} updated'.format(data
)
4339 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
4340 if controller_id
== None:
4341 data
= ovim
.get_of_controllers()
4343 data
= ovim
.show_of_controller(controller_id
)
4345 msg
= 'SDN controller list:\n {}'.format(data
)
4349 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
4350 select_
= ('uuid', 'config')
4351 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
4352 for datacenter
in datacenters
:
4353 if datacenter
['config']:
4354 config
= yaml
.load(datacenter
['config'])
4355 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
4356 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
4358 data
= ovim
.delete_of_controller(controller_id
)
4359 msg
= 'SDN controller {} deleted'.format(data
)
4363 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
4364 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
4365 if len(controller
) < 1:
4366 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
4369 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
4371 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
4373 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
4374 switch_dpid
= sdn_controller
["dpid"]
4377 for compute_node
in sdn_port_mapping
:
4378 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
4380 element
["compute_node"] = compute_node
["compute_node"]
4381 for port
in compute_node
["ports"]:
4382 element
["pci"] = port
.get("pci")
4383 element
["switch_port"] = port
.get("switch_port")
4384 element
["switch_mac"] = port
.get("switch_mac")
4385 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
4386 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
4387 " or 'switch_mac'", HTTP_Bad_Request
)
4388 maps
.append(dict(element
))
4390 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
4392 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
4393 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
4396 "sdn-controller": None,
4397 "datacenter-id": datacenter_id
,
4399 "ports_mapping": list()
4402 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
4403 if datacenter
['config']:
4404 config
= yaml
.load(datacenter
['config'])
4405 if 'sdn-controller' in config
:
4406 controller_id
= config
['sdn-controller']
4407 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
4408 result
["sdn-controller"] = controller_id
4409 result
["dpid"] = sdn_controller
["dpid"]
4411 if result
["sdn-controller"] == None:
4412 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), HTTP_Bad_Request
)
4413 if result
["dpid"] == None:
4414 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
4415 HTTP_Internal_Server_Error
)
4420 ports_correspondence_dict
= dict()
4422 if result
["sdn-controller"] != link
["ofc_id"]:
4423 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
4424 if result
["dpid"] != link
["switch_dpid"]:
4425 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
4427 element
["pci"] = link
["pci"]
4428 if link
["switch_port"]:
4429 element
["switch_port"] = link
["switch_port"]
4430 if link
["switch_mac"]:
4431 element
["switch_mac"] = link
["switch_mac"]
4433 if not link
["compute_node"] in ports_correspondence_dict
:
4435 content
["compute_node"] = link
["compute_node"]
4436 content
["ports"] = list()
4437 ports_correspondence_dict
[link
["compute_node"]] = content
4439 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
4441 for key
in sorted(ports_correspondence_dict
):
4442 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
4446 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
4447 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})
4449 def create_RO_keypair(tenant_id
):
4451 Creates a public / private keys for a RO tenant and returns their values
4453 tenant_id: ID of the tenant
4455 public_key: Public key for the RO tenant
4456 private_key: Encrypted private key for RO tenant
4460 key
= RSA
.generate(bits
)
4462 public_key
= key
.publickey().exportKey('OpenSSH')
4463 if isinstance(public_key
, ValueError):
4464 raise NfvoException("Unable to create public key: {}".format(public_key
), HTTP_Internal_Server_Error
)
4465 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
4466 except (ValueError, NameError) as e
:
4467 raise NfvoException("Unable to create private key: {}".format(e
), HTTP_Internal_Server_Error
)
4468 return public_key
, private_key
4470 def decrypt_key (key
, tenant_id
):
4472 Decrypts an encrypted RSA key
4474 key: Private key to be decrypted
4475 tenant_id: ID of the tenant
4477 unencrypted_key: Unencrypted private key for RO tenant
4480 key
= RSA
.importKey(key
,tenant_id
)
4481 unencrypted_key
= key
.exportKey('PEM')
4482 if isinstance(unencrypted_key
, ValueError):
4483 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), HTTP_Internal_Server_Error
)
4484 except ValueError as e
:
4485 raise NfvoException("Unable to decrypt the private key: {}".format(e
), HTTP_Internal_Server_Error
)
4486 return unencrypted_key