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 for vnfd_yang
in myvnfd
.vnfd_catalog
.vnfd
.itervalues():
807 vnfd
= vnfd_yang
.get()
810 vnf_uuid
= str(uuid4())
811 uuid_list
.append(vnf_uuid
)
812 vnfd_uuid_list
.append(vnf_uuid
)
815 "osm_id": get_str(vnfd
, "id", 255),
816 "name": get_str(vnfd
, "name", 255),
817 "description": get_str(vnfd
, "description", 255),
818 "tenant_id": tenant_id
,
819 "vendor": get_str(vnfd
, "vendor", 255),
820 "short_name": get_str(vnfd
, "short-name", 255),
821 "descriptor": str(vnf_descriptor
)[:60000]
824 # table nets (internal-vld)
825 net_id2uuid
= {} # for mapping interface with network
826 for vld
in vnfd
.get("internal-vld").itervalues():
827 net_uuid
= str(uuid4())
828 uuid_list
.append(net_uuid
)
830 "name": get_str(vld
, "name", 255),
833 "description": get_str(vld
, "description", 255),
834 "type": "bridge", # TODO adjust depending on connection point type
836 net_id2uuid
[vld
.get("id")] = net_uuid
837 db_nets
.append(db_net
)
841 vdu_id2db_table_index
= {}
842 for vdu
in vnfd
.get("vdu").itervalues():
843 vm_uuid
= str(uuid4())
844 uuid_list
.append(vm_uuid
)
847 "osm_id": get_str(vdu
, "id", 255),
848 "name": get_str(vdu
, "name", 255),
849 "description": get_str(vdu
, "description", 255),
852 vdu_id2uuid
[db_vm
["osm_id"]] = vm_uuid
853 vdu_id2db_table_index
[db_vm
["osm_id"]] = db_vms_index
855 db_vm
["count"] = int(vdu
["count"])
858 image_present
= False
862 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, vdu
)
864 image_uuid
= db_image
["uuid"]
865 db_images
.append(db_image
)
866 db_vm
["image_id"] = image_uuid
870 if vdu
.get("volumes"):
871 for volume_key
in sorted(vdu
["volumes"]):
872 volume
= vdu
["volumes"][volume_key
]
873 if not image_present
:
874 # Convert the first volume to vnfc.image
877 image_uuid
= _lookfor_or_create_image(db_image
, mydb
, volume
)
879 image_uuid
= db_image
["uuid"]
880 db_images
.append(db_image
)
881 db_vm
["image_id"] = image_uuid
883 # Add Openmano devices
885 device
["type"] = str(volume
.get("device-type"))
886 if volume
.get("size"):
887 device
["size"] = int(volume
["size"])
888 if volume
.get("image"):
889 device
["image name"] = str(volume
["image"])
890 if volume
.get("image-checksum"):
891 device
["image checksum"] = str(volume
["image-checksum"])
892 devices
.append(device
)
896 "name": get_str(vdu
, "name", 250) + "-flv",
897 "vcpus": int(vdu
["vm-flavor"].get("vcpu-count", 1)),
898 "ram": int(vdu
["vm-flavor"].get("memory-mb", 1)),
899 "disk": int(vdu
["vm-flavor"].get("storage-gb", 1)),
905 extended
["devices"] = devices
906 if vdu
.get("guest-epa"): # TODO or dedicated_int:
908 if vdu
["guest-epa"].get("numa-node-policy"): # TODO or dedicated_int:
909 numa_node_policy
= vdu
["guest-epa"].get("numa-node-policy")
910 if numa_node_policy
.get("node"):
911 numa_node
= numa_node_policy
["node"]['0']
912 if numa_node
.get("num-cores"):
913 numa
["cores"] = numa_node
["num-cores"]
915 if numa_node
.get("paired-threads"):
916 if numa_node
["paired-threads"].get("num-paired-threads"):
917 numa
["paired-threads"] = int(numa_node
["paired-threads"]["num-paired-threads"])
919 if len(numa_node
["paired-threads"].get("paired-thread-ids")):
920 numa
["paired-threads-id"] = []
921 for pair
in numa_node
["paired-threads"]["paired-thread-ids"].itervalues():
922 numa
["paired-threads-id"].append(
923 (str(pair
["thread-a"]), str(pair
["thread-b"]))
925 if numa_node
.get("num-threads"):
926 numa
["threads"] = int(numa_node
["num-threads"])
928 if numa_node
.get("memory-mb"):
929 numa
["memory"] = max(int(numa_node
["memory-mb"] / 1024), 1)
930 if vdu
["guest-epa"].get("mempage-size"):
931 if vdu
["guest-epa"]["mempage-size"] != "SMALL":
932 numa
["memory"] = max(int(db_flavor
["ram"] / 1024), 1)
933 if vdu
["guest-epa"].get("cpu-pinning-policy") and not epa_vcpu_set
:
934 if vdu
["guest-epa"]["cpu-pinning-policy"] == "DEDICATED":
935 if vdu
["guest-epa"].get("cpu-thread-pinning-policy") and \
936 vdu
["guest-epa"]["cpu-thread-pinning-policy"] != "PREFER":
937 numa
["cores"] = max(db_flavor
["vcpus"], 1)
939 numa
["threads"] = max(db_flavor
["vcpus"], 1)
941 extended
["numas"] = [numa
]
943 extended_text
= yaml
.safe_dump(extended
, default_flow_style
=True, width
=256)
944 db_flavor
["extended"] = extended_text
945 # look if flavor exist
947 temp_flavor_dict
= {'disk': db_flavor
.get('disk', 1),
948 'ram': db_flavor
.get('ram'),
949 'vcpus': db_flavor
.get('vcpus'),
950 'extended': db_flavor
.get('extended')
952 existing_flavors
= mydb
.get_rows(FROM
="flavors", WHERE
=temp_flavor_dict
)
954 flavor_uuid
= existing_flavors
[0]["uuid"]
956 flavor_uuid
= str(uuid4())
957 uuid_list
.append(flavor_uuid
)
958 db_flavor
["uuid"] = flavor_uuid
959 db_flavors
.append(db_flavor
)
960 db_vm
["flavor_id"] = flavor_uuid
964 if vdu
.get("cloud-init"):
965 boot_data
["user-data"] = str(vdu
["cloud-init"])
966 elif vdu
.get("cloud-init-file"):
967 # TODO Where this file content is present???
968 # boot_data["user-data"] = vnfd_yang.files[vdu["cloud-init-file"]]
969 boot_data
["user-data"] = str(vdu
["cloud-init-file"])
971 if vdu
.get("supplemental-boot-data"):
972 if vdu
["supplemental-boot-data"].get('boot-data-drive'):
973 boot_data
['boot-data-drive'] = True
974 if vdu
["supplemental-boot-data"].get('config-file'):
975 om_cfgfile_list
= list()
976 for custom_config_file
in vdu
["supplemental-boot-data"]['config-file'].itervalues():
977 # TODO Where this file content is present???
978 cfg_source
= str(custom_config_file
["source"])
979 om_cfgfile_list
.append({"dest": custom_config_file
["dest"],
980 "content": cfg_source
})
981 boot_data
['config-files'] = om_cfgfile_list
983 db_vm
["boot_data"] = yaml
.safe_dump(boot_data
, default_flow_style
=True, width
=256)
988 # table interfaces (internal/external interfaces)
989 cp_name2iface_uuid
= {}
991 # for iface in chain(vdu.get("internal-interface").itervalues(), vdu.get("external-interface").itervalues()):
992 for iface
in vdu
.get("interface").itervalues():
993 iface_uuid
= str(uuid4())
994 uuid_list
.append(iface_uuid
)
997 "internal_name": get_str(iface
, "name", 255),
1000 if iface
.get("virtual-interface").get("vpci"):
1001 db_interface
["vpci"] = get_str(iface
.get("virtual-interface"), "vpci", 12)
1003 if iface
.get("virtual-interface").get("bandwidth"):
1004 bps
= int(iface
.get("virtual-interface").get("bandwidth"))
1005 db_interface
["bw"] = bps
/1000
1007 if iface
.get("virtual-interface").get("type") == "OM-MGMT":
1008 db_interface
["type"] = "mgmt"
1009 elif iface
.get("virtual-interface").get("type") in ("VIRTIO", "E1000"):
1010 db_interface
["type"] = "bridge"
1011 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1012 elif iface
.get("virtual-interface").get("type") in ("SR-IOV", "PCI-PASSTHROUGH"):
1013 db_interface
["type"] = "data"
1014 db_interface
["model"] = get_str(iface
.get("virtual-interface"), "type", 12)
1016 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{}]':'vdu[{}]':'interface':'virtual"
1017 "-interface':'type':'{}'. Interface type is not supported".format(
1018 str(vnfd
["id"])[:255], str(vdu
["id"])[:255],
1019 iface
.get("virtual-interface").get("type")),
1022 if iface
.get("external-connection-point-ref"):
1024 cp
= vnfd
.get("connection-point")[iface
.get("external-connection-point-ref")]
1025 db_interface
["external_name"] = get_str(cp
, "name", 255)
1026 cp_name2iface_uuid
[db_interface
["external_name"]] = iface_uuid
1027 cp_name2vm_uuid
[db_interface
["external_name"]] = vm_uuid
1028 if cp
.get("port-security-enabled") == False:
1029 db_interface
["port_security"] = 0
1030 elif cp
.get("port-security-enabled") == True:
1031 db_interface
["port_security"] = 1
1033 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1034 "'interface[{iface}]':'vnfd-connection-point-ref':'{cp}' is not present"
1035 " at connection-point".format(
1036 vnf
=vnfd
["id"], vdu
=vdu
["id"], iface
=iface
["name"],
1037 cp
=iface
.get("vnfd-connection-point-ref")),
1039 elif iface
.get("internal-connection-point-ref"):
1041 for vld
in vnfd
.get("internal-vld").itervalues():
1042 for cp
in vld
.get("internal-connection-point").itervalues():
1043 if cp
.get("id-ref") == iface
.get("internal-connection-point-ref"):
1044 db_interface
["net_id"] = net_id2uuid
[vld
.get("id")]
1045 if cp
.get("port-security-enabled") == False:
1046 db_interface
["port_security"] = 0
1047 elif cp
.get("port-security-enabled") == True:
1048 db_interface
["port_security"] = 1
1051 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'vdu[{vdu}]':"
1052 "'interface[{iface}]':'vdu-internal-connection-point-ref':'{cp}' is not"
1053 " referenced by any internal-vld".format(
1054 vnf
=vnfd
["id"], vdu
=vdu
["id"], iface
=iface
["name"],
1055 cp
=iface
.get("vdu-internal-connection-point-ref")),
1057 if iface
.get("position") is not None:
1058 db_interface
["created_at"] = int(iface
.get("position")) - 1000
1059 db_interfaces
.append(db_interface
)
1061 # VNF affinity and antiaffinity
1062 for pg
in vnfd
.get("placement-groups").itervalues():
1063 pg_name
= get_str(pg
, "name", 255)
1064 for vdu
in pg
.get("member-vdus").itervalues():
1065 vdu_id
= get_str(vdu
, "member-vdu-ref", 255)
1066 if vdu_id
not in vdu_id2db_table_index
:
1067 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'placement-groups[{pg}]':"
1068 "'member-vdus':'{vdu}'. Reference to a non-existing vdu".format(
1069 vnf
=vnfd
["id"], pg
=pg_name
, vdu
=vdu_id
),
1071 db_vms
[vdu_id2db_table_index
[vdu_id
]]["availability_zone"] = pg_name
1072 # TODO consider the case of isolation and not colocation
1073 # if pg.get("strategy") == "ISOLATION":
1075 # VNF mgmt configuration
1077 if vnfd
["mgmt-interface"].get("vdu-id"):
1078 if vnfd
["mgmt-interface"]["vdu-id"] not in vdu_id2uuid
:
1079 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'vdu-id':"
1080 "'{vdu}'. Reference to a non-existing vdu".format(
1081 vnf
=vnfd
["id"], vdu
=vnfd
["mgmt-interface"]["vdu-id"]),
1083 mgmt_access
["vm_id"] = vdu_id2uuid
[vnfd
["mgmt-interface"]["vdu-id"]]
1084 if vnfd
["mgmt-interface"].get("ip-address"):
1085 mgmt_access
["ip-address"] = str(vnfd
["mgmt-interface"].get("ip-address"))
1086 if vnfd
["mgmt-interface"].get("cp"):
1087 if vnfd
["mgmt-interface"]["cp"] not in cp_name2iface_uuid
:
1088 raise NfvoException("Error. Invalid VNF descriptor at 'vnfd[{vnf}]':'mgmt-interface':'cp':'{cp}'. "
1089 "Reference to a non-existing connection-point".format(
1090 vnf
=vnfd
["id"], cp
=vnfd
["mgmt-interface"]["cp"]),
1092 mgmt_access
["vm_id"] = cp_name2vm_uuid
[vnfd
["mgmt-interface"]["cp"]]
1093 mgmt_access
["interface_id"] = cp_name2iface_uuid
[vnfd
["mgmt-interface"]["cp"]]
1094 default_user
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1098 mgmt_access
["default_user"] = default_user
1099 required
= get_str(vnfd
.get("vnf-configuration", {}).get("config-access", {}).get("ssh-access", {}),
1102 mgmt_access
["required"] = required
1105 db_vnf
["mgmt_access"] = yaml
.safe_dump(mgmt_access
, default_flow_style
=True, width
=256)
1109 db_vnfs
.append(db_vnf
)
1113 {"images": db_images
},
1114 {"flavors": db_flavors
},
1116 {"interfaces": db_interfaces
},
1119 logger
.debug("create_vnf Deployment done vnfDict: %s",
1120 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
1121 mydb
.new_rows(db_tables
, uuid_list
)
1122 return vnfd_uuid_list
1123 except NfvoException
:
1125 except Exception as e
:
1126 logger
.error("Exception {}".format(e
))
1127 raise # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
1130 def new_vnf(mydb
, tenant_id
, vnf_descriptor
):
1131 global global_config
1133 # Step 1. Check the VNF descriptor
1134 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=1)
1135 # Step 2. Check tenant exist
1137 if tenant_id
!= "any":
1138 check_tenant(mydb
, tenant_id
)
1139 if "tenant_id" in vnf_descriptor
["vnf"]:
1140 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1141 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1144 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1145 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1146 if global_config
["auto_push_VNF_to_VIMs"]:
1147 vims
= get_vim(mydb
, tenant_id
)
1149 # Step 4. Review the descriptor and add missing fields
1150 #print vnf_descriptor
1151 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1152 vnf_name
= vnf_descriptor
['vnf']['name']
1153 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1154 if "physical" in vnf_descriptor
['vnf']:
1155 del vnf_descriptor
['vnf']['physical']
1156 #print vnf_descriptor
1158 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1159 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1160 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1162 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1163 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1164 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1166 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1167 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1169 VNFCitem
["name"] = vnfc
['name']
1170 VNFCitem
["availability_zone"] = vnfc
.get('availability_zone')
1171 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1173 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1176 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1177 myflavorDict
["description"] = VNFCitem
["description"]
1178 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1179 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1180 myflavorDict
["disk"] = vnfc
.get("disk", 1)
1181 myflavorDict
["extended"] = {}
1183 devices
= vnfc
.get("devices")
1185 myflavorDict
["extended"]["devices"] = devices
1188 # 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
1189 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1191 # Previous code has been commented
1192 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1193 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1194 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1195 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1197 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1199 # print "Error creating flavor: unknown processor model. Rollback successful."
1200 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1202 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1203 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1205 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1206 myflavorDict
['extended']['numas'] = vnfc
['numas']
1210 # Step 6.2 New flavors are created in the VIM
1211 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1213 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1214 VNFCitem
["flavor_id"] = flavor_id
1215 VNFCDict
[vnfc
['name']] = VNFCitem
1217 logger
.debug("Creating new images in the VIM for each VNFC")
1218 # Step 6.3 New images are created in the VIM
1219 #For each VNFC, we must create the appropriate image.
1220 #This "for" loop might be integrated with the previous one
1221 #In case this integration is made, the VNFCDict might become a VNFClist.
1222 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1223 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1225 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1226 image_dict
['universal_name']=vnfc
.get('image name')
1227 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1228 image_dict
['location']=vnfc
.get('VNFC image')
1229 #image_dict['new_location']=vnfc.get('image location')
1230 image_dict
['checksum']=vnfc
.get('image checksum')
1231 image_metadata_dict
= vnfc
.get('image metadata', None)
1232 image_metadata_str
= None
1233 if image_metadata_dict
is not None:
1234 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1235 image_dict
['metadata']=image_metadata_str
1236 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1237 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1238 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1239 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1240 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1241 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1242 if vnfc
.get("boot-data"):
1243 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1246 # Step 7. Storing the VNF descriptor in the repository
1247 if "descriptor" not in vnf_descriptor
["vnf"]:
1248 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1250 # Step 8. Adding the VNF to the NFVO DB
1251 vnf_id
= mydb
.new_vnf_as_a_whole(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1253 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1254 _
, message
= rollback(mydb
, vims
, rollback_list
)
1255 if isinstance(e
, db_base_Exception
):
1256 error_text
= "Exception at database"
1257 elif isinstance(e
, KeyError):
1258 error_text
= "KeyError exception "
1259 e
.http_code
= HTTP_Internal_Server_Error
1261 error_text
= "Exception at VIM"
1262 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1263 #logger.error("start_scenario %s", error_text)
1264 raise NfvoException(error_text
, e
.http_code
)
1267 def new_vnf_v02(mydb
, tenant_id
, vnf_descriptor
):
1268 global global_config
1270 # Step 1. Check the VNF descriptor
1271 check_vnf_descriptor(vnf_descriptor
, vnf_descriptor_version
=2)
1272 # Step 2. Check tenant exist
1274 if tenant_id
!= "any":
1275 check_tenant(mydb
, tenant_id
)
1276 if "tenant_id" in vnf_descriptor
["vnf"]:
1277 if vnf_descriptor
["vnf"]["tenant_id"] != tenant_id
:
1278 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(vnf_descriptor
["vnf"]["tenant_id"], tenant_id
),
1281 vnf_descriptor
['vnf']['tenant_id'] = tenant_id
1282 # Step 3. Get the URL of the VIM from the nfvo_tenant and the datacenter
1283 if global_config
["auto_push_VNF_to_VIMs"]:
1284 vims
= get_vim(mydb
, tenant_id
)
1286 # Step 4. Review the descriptor and add missing fields
1287 #print vnf_descriptor
1288 #logger.debug("Refactoring VNF descriptor with fields: description, public (default: true)")
1289 vnf_name
= vnf_descriptor
['vnf']['name']
1290 vnf_descriptor
['vnf']['description'] = vnf_descriptor
['vnf'].get("description", vnf_name
)
1291 if "physical" in vnf_descriptor
['vnf']:
1292 del vnf_descriptor
['vnf']['physical']
1293 #print vnf_descriptor
1295 # Step 6. For each VNFC in the descriptor, flavors and images are created in the VIM
1296 logger
.debug('BEGIN creation of VNF "%s"' % vnf_name
)
1297 logger
.debug("VNF %s: consisting of %d VNFC(s)" % (vnf_name
,len(vnf_descriptor
['vnf']['VNFC'])))
1299 #For each VNFC, we add it to the VNFCDict and we create a flavor.
1300 VNFCDict
= {} # Dictionary, key: VNFC name, value: dict with the relevant information to create the VNF and VMs in the MANO database
1301 rollback_list
= [] # It will contain the new images created in mano. It is used for rollback
1303 logger
.debug("Creating additional disk images and new flavors in the VIM for each VNFC")
1304 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1306 VNFCitem
["name"] = vnfc
['name']
1307 VNFCitem
["description"] = vnfc
.get("description", 'VM %s of the VNF %s' %(vnfc
['name'],vnf_name
))
1309 #print "Flavor name: %s. Description: %s" % (VNFCitem["name"]+"-flv", VNFCitem["description"])
1312 myflavorDict
["name"] = vnfc
['name']+"-flv" #Maybe we could rename the flavor by using the field "image name" if exists
1313 myflavorDict
["description"] = VNFCitem
["description"]
1314 myflavorDict
["ram"] = vnfc
.get("ram", 0)
1315 myflavorDict
["vcpus"] = vnfc
.get("vcpus", 0)
1316 myflavorDict
["disk"] = vnfc
.get("disk", 1)
1317 myflavorDict
["extended"] = {}
1319 devices
= vnfc
.get("devices")
1321 myflavorDict
["extended"]["devices"] = devices
1324 # 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
1325 # Another option is that the processor in the VNF descriptor specifies directly the ranking of the host
1327 # Previous code has been commented
1328 #if vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-4620 0 @ 2.20GHz" :
1329 # myflavorDict["flavor"]['extended']['processor_ranking'] = 200
1330 #elif vnfc['processor']['model'] == "Intel(R) Xeon(R) CPU E5-2697 v2 @ 2.70GHz" :
1331 # myflavorDict["flavor"]['extended']['processor_ranking'] = 300
1333 # result2, message = rollback(myvim, myvimURL, myvim_tenant, flavorList, imageList)
1335 # print "Error creating flavor: unknown processor model. Rollback successful."
1336 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback successful."
1338 # return -HTTP_Bad_Request, "Error creating flavor: unknown processor model. Rollback fail: you need to access VIM and delete the following %s" % message
1339 myflavorDict
['extended']['processor_ranking'] = 100 #Hardcoded value, while we decide when the mapping is done
1341 if 'numas' in vnfc
and len(vnfc
['numas'])>0:
1342 myflavorDict
['extended']['numas'] = vnfc
['numas']
1346 # Step 6.2 New flavors are created in the VIM
1347 flavor_id
= create_or_use_flavor(mydb
, vims
, myflavorDict
, rollback_list
)
1349 #print "Flavor id for VNFC %s: %s" % (vnfc['name'],flavor_id)
1350 VNFCitem
["flavor_id"] = flavor_id
1351 VNFCDict
[vnfc
['name']] = VNFCitem
1353 logger
.debug("Creating new images in the VIM for each VNFC")
1354 # Step 6.3 New images are created in the VIM
1355 #For each VNFC, we must create the appropriate image.
1356 #This "for" loop might be integrated with the previous one
1357 #In case this integration is made, the VNFCDict might become a VNFClist.
1358 for vnfc
in vnf_descriptor
['vnf']['VNFC']:
1359 #print "Image name: %s. Description: %s" % (vnfc['name']+"-img", VNFCDict[vnfc['name']]['description'])
1361 image_dict
['name']=vnfc
.get('image name',vnf_name
+"-"+vnfc
['name']+"-img")
1362 image_dict
['universal_name']=vnfc
.get('image name')
1363 image_dict
['description']=vnfc
.get('image name', VNFCDict
[vnfc
['name']]['description'])
1364 image_dict
['location']=vnfc
.get('VNFC image')
1365 #image_dict['new_location']=vnfc.get('image location')
1366 image_dict
['checksum']=vnfc
.get('image checksum')
1367 image_metadata_dict
= vnfc
.get('image metadata', None)
1368 image_metadata_str
= None
1369 if image_metadata_dict
is not None:
1370 image_metadata_str
= yaml
.safe_dump(image_metadata_dict
,default_flow_style
=True,width
=256)
1371 image_dict
['metadata']=image_metadata_str
1372 #print "create_or_use_image", mydb, vims, image_dict, rollback_list
1373 image_id
= create_or_use_image(mydb
, vims
, image_dict
, rollback_list
)
1374 #print "Image id for VNFC %s: %s" % (vnfc['name'],image_id)
1375 VNFCDict
[vnfc
['name']]["image_id"] = image_id
1376 VNFCDict
[vnfc
['name']]["image_path"] = vnfc
.get('VNFC image')
1377 VNFCDict
[vnfc
['name']]["count"] = vnfc
.get('count', 1)
1378 if vnfc
.get("boot-data"):
1379 VNFCDict
[vnfc
['name']]["boot_data"] = yaml
.safe_dump(vnfc
["boot-data"], default_flow_style
=True, width
=256)
1381 # Step 7. Storing the VNF descriptor in the repository
1382 if "descriptor" not in vnf_descriptor
["vnf"]:
1383 vnf_descriptor
["vnf"]["descriptor"] = yaml
.safe_dump(vnf_descriptor
, indent
=4, explicit_start
=True, default_flow_style
=False)
1385 # Step 8. Adding the VNF to the NFVO DB
1386 vnf_id
= mydb
.new_vnf_as_a_whole2(tenant_id
,vnf_name
,vnf_descriptor
,VNFCDict
)
1388 except (db_base_Exception
, vimconn
.vimconnException
, KeyError) as e
:
1389 _
, message
= rollback(mydb
, vims
, rollback_list
)
1390 if isinstance(e
, db_base_Exception
):
1391 error_text
= "Exception at database"
1392 elif isinstance(e
, KeyError):
1393 error_text
= "KeyError exception "
1394 e
.http_code
= HTTP_Internal_Server_Error
1396 error_text
= "Exception at VIM"
1397 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
1398 #logger.error("start_scenario %s", error_text)
1399 raise NfvoException(error_text
, e
.http_code
)
1402 def get_vnf_id(mydb
, tenant_id
, vnf_id
):
1403 #check valid tenant_id
1404 check_tenant(mydb
, tenant_id
)
1407 if tenant_id
!= "any":
1408 where_or
["tenant_id"] = tenant_id
1409 where_or
["public"] = True
1410 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1412 vnf_id
= vnf
["uuid"]
1413 filter_keys
= ('uuid', 'name', 'description', 'public', "tenant_id", "osm_id", "created_at")
1414 filtered_content
= dict( (k
,v
) for k
,v
in vnf
.iteritems() if k
in filter_keys
)
1415 #change_keys_http2db(filtered_content, http2db_vnf, reverse=True)
1416 data
={'vnf' : filtered_content
}
1418 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id',
1419 SELECT
=('vms.uuid as uuid', 'vms.osm_id as osm_id', 'vms.name as name', 'vms.description as description',
1421 WHERE
={'vnfs.uuid': vnf_id
} )
1423 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1424 # change boot_data into boot-data
1426 if vm
.get("boot_data"):
1427 vm
["boot-data"] = yaml
.safe_load(vm
["boot_data"])
1430 data
['vnf']['VNFC'] = content
1431 #TODO: GET all the information from a VNFC and include it in the output.
1434 content
= mydb
.get_rows(FROM
='vnfs join nets on vnfs.uuid=nets.vnf_id',
1435 SELECT
=('nets.uuid as uuid','nets.name as name','nets.description as description', 'nets.type as type', 'nets.multipoint as multipoint'),
1436 WHERE
={'vnfs.uuid': vnf_id
} )
1437 data
['vnf']['nets'] = content
1439 #GET ip-profile for each net
1440 for net
in data
['vnf']['nets']:
1441 ipprofiles
= mydb
.get_rows(FROM
='ip_profiles',
1442 SELECT
=('ip_version','subnet_address','gateway_address','dns_address','dhcp_enabled','dhcp_start_address','dhcp_count'),
1443 WHERE
={'net_id': net
["uuid"]} )
1444 if len(ipprofiles
)==1:
1445 net
["ip_profile"] = ipprofiles
[0]
1446 elif len(ipprofiles
)>1:
1447 raise NfvoException("More than one ip-profile found with this criteria: net_id='{}'".format(net
['uuid']), HTTP_Bad_Request
)
1450 #TODO: For each net, GET its elements and relevant info per element (VNFC, iface, ip_address) and include them in the output.
1452 #GET External Interfaces
1453 content
= mydb
.get_rows(FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces on vms.uuid=interfaces.vm_id',\
1454 SELECT
=('interfaces.uuid as uuid','interfaces.external_name as external_name', 'vms.name as vm_name', 'interfaces.vm_id as vm_id', \
1455 'interfaces.internal_name as internal_name', 'interfaces.type as type', 'interfaces.vpci as vpci','interfaces.bw as bw'),\
1456 WHERE
={'vnfs.uuid': vnf_id
},
1457 WHERE_NOT
={'interfaces.external_name': None} )
1459 data
['vnf']['external-connections'] = content
1464 def delete_vnf(mydb
,tenant_id
,vnf_id
,datacenter
=None,vim_tenant
=None):
1465 # Check tenant exist
1466 if tenant_id
!= "any":
1467 check_tenant(mydb
, tenant_id
)
1468 # Get the URL of the VIM from the nfvo_tenant and the datacenter
1469 vims
= get_vim(mydb
, tenant_id
)
1473 # Checking if it is a valid uuid and, if not, getting the uuid assuming that the name was provided"
1475 if tenant_id
!= "any":
1476 where_or
["tenant_id"] = tenant_id
1477 where_or
["public"] = True
1478 vnf
= mydb
.get_table_by_uuid_name('vnfs', vnf_id
, "VNF", WHERE_OR
=where_or
, WHERE_AND_OR
="AND")
1479 vnf_id
= vnf
["uuid"]
1481 # "Getting the list of flavors and tenants of the VNF"
1482 flavorList
= get_flavorlist(mydb
, vnf_id
)
1483 if len(flavorList
)==0:
1484 logger
.warn("delete_vnf error. No flavors found for the VNF id '%s'", vnf_id
)
1486 imageList
= get_imagelist(mydb
, vnf_id
)
1487 if len(imageList
)==0:
1488 logger
.warn( "delete_vnf error. No images found for the VNF id '%s'", vnf_id
)
1490 deleted
= mydb
.delete_row_by_id('vnfs', vnf_id
)
1492 raise NfvoException("vnf '{}' not found".format(vnf_id
), HTTP_Not_Found
)
1495 for flavor
in flavorList
:
1496 #check if flavor is used by other vnf
1498 c
= mydb
.get_rows(FROM
='vms', WHERE
={'flavor_id':flavor
} )
1500 logger
.debug("Flavor '%s' not deleted because it is being used by another VNF", flavor
)
1502 #flavor not used, must be deleted
1504 c
= mydb
.get_rows(FROM
='datacenters_flavors', WHERE
={'flavor_id':flavor
})
1505 for flavor_vim
in c
:
1506 if flavor_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1508 if flavor_vim
['created']=='false': #skip this flavor because not created by openmano
1510 myvim
=vims
[ flavor_vim
["datacenter_id"] ]
1512 myvim
.delete_flavor(flavor_vim
["vim_id"])
1513 except vimconn
.vimconnNotFoundException
as e
:
1514 logger
.warn("VIM flavor %s not exist at datacenter %s", flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] )
1515 except vimconn
.vimconnException
as e
:
1516 logger
.error("Not possible to delete VIM flavor %s from datacenter %s: %s %s",
1517 flavor_vim
["vim_id"], flavor_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1518 undeletedItems
.append("flavor {} from VIM {}".format(flavor_vim
["vim_id"], flavor_vim
["datacenter_id"] ))
1519 #delete flavor from Database, using table flavors and with cascade foreign key also at datacenters_flavors
1520 mydb
.delete_row_by_id('flavors', flavor
)
1521 except db_base_Exception
as e
:
1522 logger
.error("delete_vnf_error. Not possible to get flavor details and delete '%s'. %s", flavor
, str(e
))
1523 undeletedItems
.append("flavor %s" % flavor
)
1526 for image
in imageList
:
1528 #check if image is used by other vnf
1529 c
= mydb
.get_rows(FROM
='vms', WHERE
={'image_id':image
} )
1531 logger
.debug("Image '%s' not deleted because it is being used by another VNF", image
)
1533 #image not used, must be deleted
1535 c
= mydb
.get_rows(FROM
='datacenters_images', WHERE
={'image_id':image
})
1537 if image_vim
["datacenter_vim_id"] not in vims
: # TODO change to datacenter_tenant_id
1539 if image_vim
['created']=='false': #skip this image because not created by openmano
1541 myvim
=vims
[ image_vim
["datacenter_id"] ]
1543 myvim
.delete_image(image_vim
["vim_id"])
1544 except vimconn
.vimconnNotFoundException
as e
:
1545 logger
.warn("VIM image %s not exist at datacenter %s", image_vim
["vim_id"], image_vim
["datacenter_id"] )
1546 except vimconn
.vimconnException
as e
:
1547 logger
.error("Not possible to delete VIM image %s from datacenter %s: %s %s",
1548 image_vim
["vim_id"], image_vim
["datacenter_id"], type(e
).__name
__, str(e
))
1549 undeletedItems
.append("image {} from VIM {}".format(image_vim
["vim_id"], image_vim
["datacenter_id"] ))
1550 #delete image from Database, using table images and with cascade foreign key also at datacenters_images
1551 mydb
.delete_row_by_id('images', image
)
1552 except db_base_Exception
as e
:
1553 logger
.error("delete_vnf_error. Not possible to get image details and delete '%s'. %s", image
, str(e
))
1554 undeletedItems
.append("image %s" % image
)
1556 return vnf_id
+ " " + vnf
["name"]
1558 # return "delete_vnf. Undeleted: %s" %(undeletedItems)
1561 def get_hosts_info(mydb
, nfvo_tenant_id
, datacenter_name
=None):
1562 result
, vims
= get_vim(mydb
, nfvo_tenant_id
, None, datacenter_name
)
1566 return -HTTP_Not_Found
, "datacenter '%s' not found" % datacenter_name
1567 myvim
= vims
.values()[0]
1568 result
,servers
= myvim
.get_hosts_info()
1570 return result
, servers
1571 topology
= {'name':myvim
['name'] , 'servers': servers
}
1572 return result
, topology
1575 def get_hosts(mydb
, nfvo_tenant_id
):
1576 vims
= get_vim(mydb
, nfvo_tenant_id
)
1578 raise NfvoException("No datacenter found for tenant '{}'".format(str(nfvo_tenant_id
)), HTTP_Not_Found
)
1580 #print "nfvo.datacenter_action() error. Several datacenters found"
1581 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
1582 myvim
= vims
.values()[0]
1584 hosts
= myvim
.get_hosts()
1585 logger
.debug('VIM hosts response: '+ yaml
.safe_dump(hosts
, indent
=4, default_flow_style
=False))
1587 datacenter
= {'Datacenters': [ {'name':myvim
['name'],'servers':[]} ] }
1589 server
={'name':host
['name'], 'vms':[]}
1590 for vm
in host
['instances']:
1591 #get internal name and model
1593 c
= mydb
.get_rows(SELECT
=('name',), FROM
='instance_vms as iv join vms on iv.vm_id=vms.uuid',\
1594 WHERE
={'vim_vm_id':vm
['id']} )
1596 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' not found at tidnfvo".format(vm
['id']))
1598 server
['vms'].append( {'name':vm
['name'] , 'model':c
[0]['name']} )
1600 except db_base_Exception
as e
:
1601 logger
.warn("nfvo.get_hosts virtual machine at VIM '{}' error {}".format(vm
['id'], str(e
)))
1602 datacenter
['Datacenters'][0]['servers'].append(server
)
1603 #return -400, "en construccion"
1605 #print 'datacenters '+ json.dumps(datacenter, indent=4)
1607 except vimconn
.vimconnException
as e
:
1608 raise NfvoException("Not possible to get_host_list from VIM: {}".format(str(e
)), e
.http_code
)
1611 def new_scenario(mydb
, tenant_id
, topo
):
1613 # result, vims = get_vim(mydb, tenant_id)
1615 # return result, vims
1617 if tenant_id
!= "any":
1618 check_tenant(mydb
, tenant_id
)
1619 if "tenant_id" in topo
:
1620 if topo
["tenant_id"] != tenant_id
:
1621 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(topo
["tenant_id"], tenant_id
),
1626 #1.1: get VNFs and external_networks (other_nets).
1628 other_nets
={} #external_networks, bridge_networks and data_networkds
1629 nodes
= topo
['topology']['nodes']
1630 for k
in nodes
.keys():
1631 if nodes
[k
]['type'] == 'VNF':
1633 vnfs
[k
]['ifaces'] = {}
1634 elif nodes
[k
]['type'] == 'other_network' or nodes
[k
]['type'] == 'external_network':
1635 other_nets
[k
] = nodes
[k
]
1636 other_nets
[k
]['external']=True
1637 elif nodes
[k
]['type'] == 'network':
1638 other_nets
[k
] = nodes
[k
]
1639 other_nets
[k
]['external']=False
1642 #1.2: Check that VNF are present at database table vnfs. Insert uuid, description and external interfaces
1643 for name
,vnf
in vnfs
.items():
1645 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1647 error_pos
= "'topology':'nodes':'" + name
+ "'"
1649 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1650 where
['uuid'] = vnf
['vnf_id']
1651 if 'VNF model' in vnf
:
1652 error_text
+= " 'VNF model' " + vnf
['VNF model']
1653 where
['name'] = vnf
['VNF model']
1655 raise NfvoException("Descriptor need a 'vnf_id' or 'VNF model' field at " + error_pos
, HTTP_Bad_Request
)
1657 vnf_db
= mydb
.get_rows(SELECT
=('uuid','name','description'),
1663 raise NfvoException("unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1665 raise NfvoException("more than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1666 vnf
['uuid']=vnf_db
[0]['uuid']
1667 vnf
['description']=vnf_db
[0]['description']
1668 #get external interfaces
1669 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name','i.uuid as iface_uuid', 'i.type as type'),
1670 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1671 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name':None} )
1672 for ext_iface
in ext_ifaces
:
1673 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type':ext_iface
['type']}
1675 #1.4 get list of connections
1676 conections
= topo
['topology']['connections']
1677 conections_list
= []
1678 conections_list_name
= []
1679 for k
in conections
.keys():
1680 if type(conections
[k
]['nodes'])==dict: #dict with node:iface pairs
1681 ifaces_list
= conections
[k
]['nodes'].items()
1682 elif type(conections
[k
]['nodes'])==list: #list with dictionary
1684 conection_pair_list
= map(lambda x
: x
.items(), conections
[k
]['nodes'] )
1685 for k2
in conection_pair_list
:
1688 con_type
= conections
[k
].get("type", "link")
1689 if con_type
!= "link":
1691 raise NfvoException("Format error. Reapeted network name at 'topology':'connections':'{}'".format(str(k
)), HTTP_Bad_Request
)
1692 other_nets
[k
] = {'external': False}
1693 if conections
[k
].get("graph"):
1694 other_nets
[k
]["graph"] = conections
[k
]["graph"]
1695 ifaces_list
.append( (k
, None) )
1698 if con_type
== "external_network":
1699 other_nets
[k
]['external'] = True
1700 if conections
[k
].get("model"):
1701 other_nets
[k
]["model"] = conections
[k
]["model"]
1703 other_nets
[k
]["model"] = k
1704 if con_type
== "dataplane_net" or con_type
== "bridge_net":
1705 other_nets
[k
]["model"] = con_type
1707 conections_list_name
.append(k
)
1708 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)
1709 #print set(ifaces_list)
1710 #check valid VNF and iface names
1711 for iface
in ifaces_list
:
1712 if iface
[0] not in vnfs
and iface
[0] not in other_nets
:
1713 raise NfvoException("format error. Invalid VNF name at 'topology':'connections':'{}':'nodes':'{}'".format(
1714 str(k
), iface
[0]), HTTP_Not_Found
)
1715 if iface
[0] in vnfs
and iface
[1] not in vnfs
[ iface
[0] ]['ifaces']:
1716 raise NfvoException("format error. Invalid interface name at 'topology':'connections':'{}':'nodes':'{}':'{}'".format(
1717 str(k
), iface
[0], iface
[1]), HTTP_Not_Found
)
1719 #1.5 unify connections from the pair list to a consolidated list
1721 while index
< len(conections_list
):
1723 while index2
< len(conections_list
):
1724 if len(conections_list
[index
] & conections_list
[index2
])>0: #common interface, join nets
1725 conections_list
[index
] |
= conections_list
[index2
]
1726 del conections_list
[index2
]
1727 del conections_list_name
[index2
]
1730 conections_list
[index
] = list(conections_list
[index
]) # from set to list again
1732 #for k in conections_list:
1737 #1.6 Delete non external nets
1738 # for k in other_nets.keys():
1739 # if other_nets[k]['model']=='bridge' or other_nets[k]['model']=='dataplane_net' or other_nets[k]['model']=='bridge_net':
1740 # for con in conections_list:
1742 # for index in range(0,len(con)):
1743 # if con[index][0] == k: delete_indexes.insert(0,index) #order from higher to lower
1744 # for index in delete_indexes:
1747 #1.7: Check external_ports are present at database table datacenter_nets
1748 for k
,net
in other_nets
.items():
1749 error_pos
= "'topology':'nodes':'" + k
+ "'"
1750 if net
['external']==False:
1751 if 'name' not in net
:
1753 if 'model' not in net
:
1754 raise NfvoException("needed a 'model' at " + error_pos
, HTTP_Bad_Request
)
1755 if net
['model']=='bridge_net':
1756 net
['type']='bridge';
1757 elif net
['model']=='dataplane_net':
1760 raise NfvoException("unknown 'model' '"+ net
['model'] +"' at " + error_pos
, HTTP_Not_Found
)
1762 #IF we do not want to check that external network exist at datacenter
1767 # if 'net_id' in net:
1768 # error_text += " 'net_id' " + net['net_id']
1769 # WHERE_['uuid'] = net['net_id']
1770 # if 'model' in net:
1771 # error_text += " 'model' " + net['model']
1772 # WHERE_['name'] = net['model']
1773 # if len(WHERE_) == 0:
1774 # return -HTTP_Bad_Request, "needed a 'net_id' or 'model' at " + error_pos
1775 # r,net_db = mydb.get_table(SELECT=('uuid','name','description','type','shared'),
1776 # FROM='datacenter_nets', WHERE=WHERE_ )
1778 # print "nfvo.new_scenario Error getting datacenter_nets",r,net_db
1780 # print "nfvo.new_scenario Error" +error_text+ " is not present at database"
1781 # return -HTTP_Bad_Request, "unknown " +error_text+ " at " + error_pos
1783 # print "nfvo.new_scenario Error more than one external_network for " +error_text+ " is present at database"
1784 # return -HTTP_Bad_Request, "more than one external_network for " +error_text+ "at "+ error_pos + " Concrete with 'net_id'"
1785 # other_nets[k].update(net_db[0])
1788 net_nb
=0 #Number of nets
1789 for con
in conections_list
:
1790 #check if this is connected to a external net
1794 for index
in range(0,len(con
)):
1795 #check if this is connected to a external net
1796 for net_key
in other_nets
.keys():
1797 if con
[index
][0]==net_key
:
1798 if other_net_index
>=0:
1799 error_text
="There is some interface connected both to net '%s' and net '%s'" % (con
[other_net_index
][0], net_key
)
1800 #print "nfvo.new_scenario " + error_text
1801 raise NfvoException(error_text
, HTTP_Bad_Request
)
1803 other_net_index
= index
1804 net_target
= net_key
1806 #print "other_net_index", other_net_index
1808 if other_net_index
>=0:
1809 del con
[other_net_index
]
1810 #IF we do not want to check that external network exist at datacenter
1811 if other_nets
[net_target
]['external'] :
1812 if "name" not in other_nets
[net_target
]:
1813 other_nets
[net_target
]['name'] = other_nets
[net_target
]['model']
1814 if other_nets
[net_target
]["type"] == "external_network":
1815 if vnfs
[ con
[0][0] ]['ifaces'][ con
[0][1] ]["type"] == "data":
1816 other_nets
[net_target
]["type"] = "data"
1818 other_nets
[net_target
]["type"] = "bridge"
1820 # if other_nets[net_target]['external'] :
1821 # 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
1822 # if type_=='data' and other_nets[net_target]['type']=="ptp":
1823 # error_text = "Error connecting %d nodes on a not multipoint net %s" % (len(con), net_target)
1824 # print "nfvo.new_scenario " + error_text
1825 # return -HTTP_Bad_Request, error_text
1828 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1831 net_type_bridge
=False
1833 net_target
= "__-__net"+str(net_nb
)
1834 net_list
[net_target
] = {'name': conections_list_name
[net_nb
], #"net-"+str(net_nb),
1835 'description':"net-%s in scenario %s" %(net_nb
,topo
['name']),
1838 vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['net_key'] = net_target
1839 iface_type
= vnfs
[ iface
[0] ]['ifaces'][ iface
[1] ]['type']
1840 if iface_type
=='mgmt' or iface_type
=='bridge':
1841 net_type_bridge
= True
1843 net_type_data
= True
1844 if net_type_bridge
and net_type_data
:
1845 error_text
= "Error connection interfaces of bridge type with data type. Firs node %s, iface %s" % (iface
[0], iface
[1])
1846 #print "nfvo.new_scenario " + error_text
1847 raise NfvoException(error_text
, HTTP_Bad_Request
)
1848 elif net_type_bridge
:
1851 type_
='data' if len(con
)>2 else 'ptp'
1852 net_list
[net_target
]['type'] = type_
1855 error_text
= "Error connection node %s : %s does not match any VNF or interface" % (iface
[0], iface
[1])
1856 #print "nfvo.new_scenario " + error_text
1858 raise NfvoException(error_text
, HTTP_Bad_Request
)
1860 #1.8: Connect to management net all not already connected interfaces of type 'mgmt'
1861 #1.8.1 obtain management net
1862 mgmt_net
= mydb
.get_rows(SELECT
=('uuid','name','description','type','shared'),
1863 FROM
='datacenter_nets', WHERE
={'name':'mgmt'} )
1864 #1.8.2 check all interfaces from all vnfs
1866 add_mgmt_net
= False
1867 for vnf
in vnfs
.values():
1868 for iface
in vnf
['ifaces'].values():
1869 if iface
['type']=='mgmt' and 'net_key' not in iface
:
1870 #iface not connected
1871 iface
['net_key'] = 'mgmt'
1873 if add_mgmt_net
and 'mgmt' not in net_list
:
1874 net_list
['mgmt']=mgmt_net
[0]
1875 net_list
['mgmt']['external']=True
1876 net_list
['mgmt']['graph']={'visible':False}
1878 net_list
.update(other_nets
)
1880 #print 'net_list', net_list
1885 #2: insert scenario. filling tables scenarios,sce_vnfs,sce_interfaces,sce_nets
1886 c
= mydb
.new_scenario( { 'vnfs':vnfs
, 'nets':net_list
,
1887 'tenant_id':tenant_id
, 'name':topo
['name'],
1888 'description':topo
.get('description',topo
['name']),
1889 'public': topo
.get('public', False)
1895 def new_scenario_v02(mydb
, tenant_id
, scenario_dict
, version
):
1896 """ This creates a new scenario for version 0.2 and 0.3"""
1897 scenario
= scenario_dict
["scenario"]
1898 if tenant_id
!= "any":
1899 check_tenant(mydb
, tenant_id
)
1900 if "tenant_id" in scenario
:
1901 if scenario
["tenant_id"] != tenant_id
:
1902 # print "nfvo.new_scenario_v02() tenant '%s' not found" % tenant_id
1903 raise NfvoException("VNF can not have a different tenant owner '{}', must be '{}'".format(
1904 scenario
["tenant_id"], tenant_id
), HTTP_Unauthorized
)
1908 # 1: Check that VNF are present at database table vnfs and update content into scenario dict
1909 for name
,vnf
in scenario
["vnfs"].iteritems():
1911 where_or
={"tenant_id": tenant_id
, 'public': "true"}
1913 error_pos
= "'scenario':'vnfs':'" + name
+ "'"
1915 error_text
+= " 'vnf_id' " + vnf
['vnf_id']
1916 where
['uuid'] = vnf
['vnf_id']
1917 if 'vnf_name' in vnf
:
1918 error_text
+= " 'vnf_name' " + vnf
['vnf_name']
1919 where
['name'] = vnf
['vnf_name']
1921 raise NfvoException("Needed a 'vnf_id' or 'vnf_name' at " + error_pos
, HTTP_Bad_Request
)
1922 vnf_db
= mydb
.get_rows(SELECT
=('uuid', 'name', 'description'),
1927 if len(vnf_db
) == 0:
1928 raise NfvoException("Unknown" + error_text
+ " at " + error_pos
, HTTP_Not_Found
)
1929 elif len(vnf_db
) > 1:
1930 raise NfvoException("More than one" + error_text
+ " at " + error_pos
+ " Concrete with 'vnf_id'", HTTP_Conflict
)
1931 vnf
['uuid'] = vnf_db
[0]['uuid']
1932 vnf
['description'] = vnf_db
[0]['description']
1934 # get external interfaces
1935 ext_ifaces
= mydb
.get_rows(SELECT
=('external_name as name', 'i.uuid as iface_uuid', 'i.type as type'),
1936 FROM
='vnfs join vms on vnfs.uuid=vms.vnf_id join interfaces as i on vms.uuid=i.vm_id',
1937 WHERE
={'vnfs.uuid':vnf
['uuid']}, WHERE_NOT
={'external_name': None} )
1938 for ext_iface
in ext_ifaces
:
1939 vnf
['ifaces'][ ext_iface
['name'] ] = {'uuid':ext_iface
['iface_uuid'], 'type': ext_iface
['type']}
1940 # TODO? get internal-connections from db.nets and their profiles, and update scenario[vnfs][internal-connections] accordingly
1942 # 2: Insert net_key and ip_address at every vnf interface
1943 for net_name
, net
in scenario
["networks"].items():
1944 net_type_bridge
= False
1945 net_type_data
= False
1946 for iface_dict
in net
["interfaces"]:
1947 if version
== "0.2":
1948 temp_dict
= iface_dict
1950 elif version
== "0.3":
1951 temp_dict
= {iface_dict
["vnf"] : iface_dict
["vnf_interface"]}
1952 ip_address
= iface_dict
.get('ip_address', None)
1953 for vnf
, iface
in temp_dict
.items():
1954 if vnf
not in scenario
["vnfs"]:
1955 error_text
= "Error at 'networks':'{}':'interfaces' VNF '{}' not match any VNF at 'vnfs'".format(
1957 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1958 raise NfvoException(error_text
, HTTP_Not_Found
)
1959 if iface
not in scenario
["vnfs"][vnf
]['ifaces']:
1960 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface not match any VNF interface"\
1961 .format(net_name
, iface
)
1962 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1963 raise NfvoException(error_text
, HTTP_Bad_Request
)
1964 if "net_key" in scenario
["vnfs"][vnf
]['ifaces'][iface
]:
1965 error_text
= "Error at 'networks':'{}':'interfaces':'{}' interface already connected at network"\
1966 "'{}'".format(net_name
, iface
,scenario
["vnfs"][vnf
]['ifaces'][iface
]['net_key'])
1967 # logger.debug("nfvo.new_scenario_v02 " + error_text)
1968 raise NfvoException(error_text
, HTTP_Bad_Request
)
1969 scenario
["vnfs"][vnf
]['ifaces'][ iface
]['net_key'] = net_name
1970 scenario
["vnfs"][vnf
]['ifaces'][iface
]['ip_address'] = ip_address
1971 iface_type
= scenario
["vnfs"][vnf
]['ifaces'][iface
]['type']
1972 if iface_type
== 'mgmt' or iface_type
== 'bridge':
1973 net_type_bridge
= True
1975 net_type_data
= True
1977 if net_type_bridge
and net_type_data
:
1978 error_text
= "Error connection interfaces of 'bridge' type and 'data' type at 'networks':'{}':'interfaces'"\
1980 # logger.debug("nfvo.new_scenario " + error_text)
1981 raise NfvoException(error_text
, HTTP_Bad_Request
)
1982 elif net_type_bridge
:
1985 type_
= 'data' if len(net
["interfaces"]) > 2 else 'ptp'
1987 if net
.get("implementation"): # for v0.3
1988 if type_
== "bridge" and net
["implementation"] == "underlay":
1989 error_text
= "Error connecting interfaces of data type to a network declared as 'underlay' at "\
1990 "'network':'{}'".format(net_name
)
1991 # logger.debug(error_text)
1992 raise NfvoException(error_text
, HTTP_Bad_Request
)
1993 elif type_
!= "bridge" and net
["implementation"] == "overlay":
1994 error_text
= "Error connecting interfaces of data type to a network declared as 'overlay' at "\
1995 "'network':'{}'".format(net_name
)
1996 # logger.debug(error_text)
1997 raise NfvoException(error_text
, HTTP_Bad_Request
)
1998 net
.pop("implementation")
1999 if "type" in net
and version
== "0.3": # for v0.3
2000 if type_
== "data" and net
["type"] == "e-line":
2001 error_text
= "Error connecting more than 2 interfaces of data type to a network declared as type "\
2002 "'e-line' at 'network':'{}'".format(net_name
)
2003 # logger.debug(error_text)
2004 raise NfvoException(error_text
, HTTP_Bad_Request
)
2005 elif type_
== "ptp" and net
["type"] == "e-lan":
2009 net
['name'] = net_name
2010 net
['external'] = net
.get('external', False)
2012 # 3: insert at database
2013 scenario
["nets"] = scenario
["networks"]
2014 scenario
['tenant_id'] = tenant_id
2015 scenario_id
= mydb
.new_scenario(scenario
)
2019 def new_nsd_v3(mydb
, tenant_id
, nsd_descriptor
):
2021 Parses an OSM IM nsd_catalog and insert at DB
2024 :param nsd_descriptor:
2025 :return: The list of cretated NSD ids
2028 mynsd
= nsd_catalog
.nsd()
2030 pybindJSONDecoder
.load_ietf_json(nsd_descriptor
, None, None, obj
=mynsd
)
2031 except Exception as e
:
2032 raise NfvoException("Error. Invalid NS descriptor format: " + str(e
), HTTP_Bad_Request
)
2036 db_sce_interfaces
= []
2038 db_ip_profiles_index
= 0
2041 for nsd_yang
in mynsd
.nsd_catalog
.nsd
.itervalues():
2042 nsd
= nsd_yang
.get()
2045 scenario_uuid
= str(uuid4())
2046 uuid_list
.append(scenario_uuid
)
2047 nsd_uuid_list
.append(scenario_uuid
)
2049 "uuid": scenario_uuid
,
2050 "osm_id": get_str(nsd
, "id", 255),
2051 "name": get_str(nsd
, "name", 255),
2052 "description": get_str(nsd
, "description", 255),
2053 "tenant_id": tenant_id
,
2054 "vendor": get_str(nsd
, "vendor", 255),
2055 "short_name": get_str(nsd
, "short-name", 255),
2056 "descriptor": str(nsd_descriptor
)[:60000],
2058 db_scenarios
.append(db_scenario
)
2060 # table sce_vnfs (constituent-vnfd)
2061 vnf_index2scevnf_uuid
= {}
2062 vnf_index2vnf_uuid
= {}
2063 for vnf
in nsd
.get("constituent-vnfd").itervalues():
2064 existing_vnf
= mydb
.get_rows(FROM
="vnfs", WHERE
={'osm_id': str(vnf
["vnfd-id-ref"])[:255],
2065 'tenant_id': tenant_id
})
2066 if not existing_vnf
:
2067 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'constituent-vnfd':'vnfd-id-ref':"
2068 "'{}'. Reference to a non-existing VNFD in the catalog".format(
2069 str(nsd
["id"]), str(vnf
["vnfd-id-ref"])[:255]),
2071 sce_vnf_uuid
= str(uuid4())
2072 uuid_list
.append(sce_vnf_uuid
)
2074 "uuid": sce_vnf_uuid
,
2075 "scenario_id": scenario_uuid
,
2076 "name": existing_vnf
[0]["name"][:200] + "." + get_str(vnf
, "member-vnf-index", 5),
2077 "vnf_id": existing_vnf
[0]["uuid"],
2078 "member_vnf_index": int(vnf
["member-vnf-index"]),
2079 # TODO 'start-by-default': True
2081 vnf_index2scevnf_uuid
[int(vnf
['member-vnf-index'])] = sce_vnf_uuid
2082 vnf_index2vnf_uuid
[int(vnf
['member-vnf-index'])] = existing_vnf
[0]["uuid"]
2083 db_sce_vnfs
.append(db_sce_vnf
)
2085 # table ip_profiles (ip-profiles)
2086 ip_profile_name2db_table_index
= {}
2087 for ip_profile
in nsd
.get("ip-profiles").itervalues():
2089 "ip_version": str(ip_profile
["ip-profile-params"].get("ip-version", "ipv4")),
2090 "subnet_address": str(ip_profile
["ip-profile-params"].get("subnet-address")),
2091 "gateway_address": str(ip_profile
["ip-profile-params"].get("gateway-address")),
2092 "dhcp_enabled": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("enabled", True)),
2093 "dhcp_start_address": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("start-address")),
2094 "dhcp_count": str(ip_profile
["ip-profile-params"]["dhcp-params"].get("count")),
2097 for dns
in ip_profile
["ip-profile-params"]["dns-server"].itervalues():
2098 dns_list
.append(str(dns
.get("address")))
2099 db_ip_profile
["dns_address"] = ";".join(dns_list
)
2100 if ip_profile
["ip-profile-params"].get('security-group'):
2101 db_ip_profile
["security_group"] = ip_profile
["ip-profile-params"]['security-group']
2102 ip_profile_name2db_table_index
[str(ip_profile
["name"])] = db_ip_profiles_index
2103 db_ip_profiles_index
+= 1
2104 db_ip_profiles
.append(db_ip_profile
)
2106 # table sce_nets (internal-vld)
2107 for vld
in nsd
.get("vld").itervalues():
2108 sce_net_uuid
= str(uuid4())
2109 uuid_list
.append(sce_net_uuid
)
2111 "uuid": sce_net_uuid
,
2112 "name": get_str(vld
, "name", 255),
2113 "scenario_id": scenario_uuid
,
2115 "multipoint": not vld
.get("type") == "ELINE",
2117 "description": get_str(vld
, "description", 255),
2119 # guess type of network
2120 if vld
.get("mgmt-network"):
2121 db_sce_net
["type"] = "bridge"
2122 db_sce_net
["external"] = True
2123 elif vld
.get("provider-network").get("overlay-type") == "VLAN":
2124 db_sce_net
["type"] = "data"
2126 db_sce_net
["type"] = "bridge"
2127 db_sce_nets
.append(db_sce_net
)
2129 # ip-profile, link db_ip_profile with db_sce_net
2130 if vld
.get("ip-profile-ref"):
2131 ip_profile_name
= vld
.get("ip-profile-ref")
2132 if ip_profile_name
not in ip_profile_name2db_table_index
:
2133 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'ip-profile-ref':'{}'."
2134 " Reference to a non-existing 'ip_profiles'".format(
2135 str(nsd
["id"]), str(vld
["id"]), str(vld
["ip-profile-ref"])),
2137 db_ip_profiles
[ip_profile_name2db_table_index
[ip_profile_name
]]["sce_net_id"] = sce_net_uuid
2139 # table sce_interfaces (vld:vnfd-connection-point-ref)
2140 for iface
in vld
.get("vnfd-connection-point-ref").itervalues():
2141 vnf_index
= int(iface
['member-vnf-index-ref'])
2142 # check correct parameters
2143 if vnf_index
not in vnf_index2vnf_uuid
:
2144 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2145 "-ref':'member-vnf-index-ref':'{}'. Reference to a non-existing index at "
2146 "'nsd':'constituent-vnfd'".format(
2147 str(nsd
["id"]), str(vld
["id"]), str(iface
["member-vnf-index-ref"])),
2150 existing_ifaces
= mydb
.get_rows(SELECT
=('i.uuid as uuid',),
2151 FROM
="interfaces as i join vms on i.vm_id=vms.uuid",
2152 WHERE
={'vnf_id': vnf_index2vnf_uuid
[vnf_index
],
2153 'external_name': get_str(iface
, "vnfd-connection-point-ref",
2155 if not existing_ifaces
:
2156 raise NfvoException("Error. Invalid NS descriptor at 'nsd[{}]':'vld[{}]':'vnfd-connection-point"
2157 "-ref':'vnfd-connection-point-ref':'{}'. Reference to a non-existing "
2158 "connection-point name at VNFD '{}'".format(
2159 str(nsd
["id"]), str(vld
["id"]), str(iface
["vnfd-connection-point-ref"]),
2160 str(iface
.get("vnfd-id-ref"))[:255]),
2162 interface_uuid
= existing_ifaces
[0]["uuid"]
2163 sce_interface_uuid
= str(uuid4())
2164 uuid_list
.append(sce_net_uuid
)
2165 db_sce_interface
= {
2166 "uuid": sce_interface_uuid
,
2167 "sce_vnf_id": vnf_index2scevnf_uuid
[vnf_index
],
2168 "sce_net_id": sce_net_uuid
,
2169 "interface_id": interface_uuid
,
2170 # "ip_address": #TODO
2172 db_sce_interfaces
.append(db_sce_interface
)
2175 {"scenarios": db_scenarios
},
2176 {"sce_nets": db_sce_nets
},
2177 {"ip_profiles": db_ip_profiles
},
2178 {"sce_vnfs": db_sce_vnfs
},
2179 {"sce_interfaces": db_sce_interfaces
},
2182 logger
.debug("create_vnf Deployment done vnfDict: %s",
2183 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
2184 mydb
.new_rows(db_tables
, uuid_list
)
2185 return nsd_uuid_list
2186 except NfvoException
:
2188 except Exception as e
:
2189 logger
.error("Exception {}".format(e
))
2190 raise # NfvoException("Exception {}".format(e), HTTP_Bad_Request)
2193 def edit_scenario(mydb
, tenant_id
, scenario_id
, data
):
2194 data
["uuid"] = scenario_id
2195 data
["tenant_id"] = tenant_id
2196 c
= mydb
.edit_scenario( data
)
2200 def start_scenario(mydb
, tenant_id
, scenario_id
, instance_scenario_name
, instance_scenario_description
, datacenter
=None,vim_tenant
=None, startvms
=True):
2201 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2202 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
, vim_tenant
=vim_tenant
)
2203 vims
= {datacenter_id
: myvim
}
2204 myvim_tenant
= myvim
['tenant_id']
2205 datacenter_name
= myvim
['name']
2209 #print "Checking that the scenario_id exists and getting the scenario dictionary"
2210 scenarioDict
= mydb
.get_scenario(scenario_id
, tenant_id
, datacenter_id
=datacenter_id
)
2211 scenarioDict
['datacenter2tenant'] = { datacenter_id
: myvim
['config']['datacenter_tenant_id'] }
2212 scenarioDict
['datacenter_id'] = datacenter_id
2213 #print '================scenarioDict======================='
2214 #print json.dumps(scenarioDict, indent=4)
2215 #print 'BEGIN launching instance scenario "%s" based on "%s"' % (instance_scenario_name,scenarioDict['name'])
2217 logger
.debug("start_scenario Scenario %s: consisting of %d VNF(s)", scenarioDict
['name'],len(scenarioDict
['vnfs']))
2218 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2220 auxNetDict
= {} #Auxiliar dictionary. First key:'scenario' or sce_vnf uuid. Second Key: uuid of the net/sce_net. Value: vim_net_id
2221 auxNetDict
['scenario'] = {}
2223 logger
.debug("start_scenario 1. Creating new nets (sce_nets) in the VIM")
2224 for sce_net
in scenarioDict
['nets']:
2225 #print "Net name: %s. Description: %s" % (sce_net["name"], sce_net["description"])
2227 myNetName
= "%s.%s" % (instance_scenario_name
, sce_net
['name'])
2228 myNetName
= myNetName
[0:255] #limit length
2229 myNetType
= sce_net
['type']
2231 myNetDict
["name"] = myNetName
2232 myNetDict
["type"] = myNetType
2233 myNetDict
["tenant_id"] = myvim_tenant
2234 myNetIPProfile
= sce_net
.get('ip_profile', None)
2236 #We should use the dictionary as input parameter for new_network
2238 if not sce_net
["external"]:
2239 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2240 #print "New VIM network created for scenario %s. Network id: %s" % (scenarioDict['name'],network_id)
2241 sce_net
['vim_id'] = network_id
2242 auxNetDict
['scenario'][sce_net
['uuid']] = network_id
2243 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2244 sce_net
["created"] = True
2246 if sce_net
['vim_id'] == None:
2247 error_text
= "Error, datacenter '%s' does not have external network '%s'." % (datacenter_name
, sce_net
['name'])
2248 _
, message
= rollback(mydb
, vims
, rollbackList
)
2249 logger
.error("nfvo.start_scenario: %s", error_text
)
2250 raise NfvoException(error_text
, HTTP_Bad_Request
)
2251 logger
.debug("Using existent VIM network for scenario %s. Network id %s", scenarioDict
['name'],sce_net
['vim_id'])
2252 auxNetDict
['scenario'][sce_net
['uuid']] = sce_net
['vim_id']
2254 logger
.debug("start_scenario 2. Creating new nets (vnf internal nets) in the VIM")
2255 #For each vnf net, we create it and we add it to instanceNetlist.
2257 for sce_vnf
in scenarioDict
['vnfs']:
2258 for net
in sce_vnf
['nets']:
2259 #print "Net name: %s. Description: %s" % (net["name"], net["description"])
2261 myNetName
= "%s.%s" % (instance_scenario_name
,net
['name'])
2262 myNetName
= myNetName
[0:255] #limit length
2263 myNetType
= net
['type']
2265 myNetDict
["name"] = myNetName
2266 myNetDict
["type"] = myNetType
2267 myNetDict
["tenant_id"] = myvim_tenant
2268 myNetIPProfile
= net
.get('ip_profile', None)
2271 #We should use the dictionary as input parameter for new_network
2272 network_id
= myvim
.new_network(myNetName
, myNetType
, myNetIPProfile
)
2273 #print "VIM network id for scenario %s: %s" % (scenarioDict['name'],network_id)
2274 net
['vim_id'] = network_id
2275 if sce_vnf
['uuid'] not in auxNetDict
:
2276 auxNetDict
[sce_vnf
['uuid']] = {}
2277 auxNetDict
[sce_vnf
['uuid']][net
['uuid']] = network_id
2278 rollbackList
.append({'what':'network','where':'vim','vim_id':datacenter_id
,'uuid':network_id
})
2279 net
["created"] = True
2281 #print "auxNetDict:"
2282 #print yaml.safe_dump(auxNetDict, indent=4, default_flow_style=False)
2284 logger
.debug("start_scenario 3. Creating new vm instances in the VIM")
2285 #myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2287 for sce_vnf
in scenarioDict
['vnfs']:
2288 vnf_availability_zones
= []
2289 for vm
in sce_vnf
['vms']:
2290 vm_av
= vm
.get('availability_zone')
2291 if vm_av
and vm_av
not in vnf_availability_zones
:
2292 vnf_availability_zones
.append(vm_av
)
2294 # check if there is enough availability zones available at vim level.
2295 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2296 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2297 raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request
)
2299 for vm
in sce_vnf
['vms']:
2302 #myVMDict['name'] = "%s-%s-%s" % (scenarioDict['name'],sce_vnf['name'], vm['name'])
2303 myVMDict
['name'] = "{}.{}.{}".format(instance_scenario_name
,sce_vnf
['name'],chr(96+i
))
2304 #myVMDict['description'] = vm['description']
2305 myVMDict
['description'] = myVMDict
['name'][0:99]
2307 myVMDict
['start'] = "no"
2308 myVMDict
['name'] = myVMDict
['name'][0:255] #limit name length
2309 #print "VM name: %s. Description: %s" % (myVMDict['name'], myVMDict['name'])
2311 #create image at vim in case it not exist
2312 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2313 image_id
= create_or_use_image(mydb
, vims
, image_dict
, [], True)
2314 vm
['vim_image_id'] = image_id
2316 #create flavor at vim in case it not exist
2317 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2318 if flavor_dict
['extended']!=None:
2319 flavor_dict
['extended']= yaml
.load(flavor_dict
['extended'])
2320 flavor_id
= create_or_use_flavor(mydb
, vims
, flavor_dict
, [], True)
2321 vm
['vim_flavor_id'] = flavor_id
2324 myVMDict
['imageRef'] = vm
['vim_image_id']
2325 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
2326 myVMDict
['networks'] = []
2327 for iface
in vm
['interfaces']:
2329 if iface
['type']=="data":
2330 netDict
['type'] = iface
['model']
2331 elif "model" in iface
and iface
["model"]!=None:
2332 netDict
['model']=iface
['model']
2333 #TODO in future, remove this because mac_address will not be set, and the type of PV,VF is obtained from iterface table model
2334 #discover type of interface looking at flavor
2335 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
2336 for flavor_iface
in numa
.get('interfaces',[]):
2337 if flavor_iface
.get('name') == iface
['internal_name']:
2338 if flavor_iface
['dedicated'] == 'yes':
2339 netDict
['type']="PF" #passthrough
2340 elif flavor_iface
['dedicated'] == 'no':
2341 netDict
['type']="VF" #siov
2342 elif flavor_iface
['dedicated'] == 'yes:sriov':
2343 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
2344 netDict
["mac_address"] = flavor_iface
.get("mac_address")
2346 netDict
["use"]=iface
['type']
2347 if netDict
["use"]=="data" and not netDict
.get("type"):
2348 #print "netDict", netDict
2349 #print "iface", iface
2350 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'])
2351 if flavor_dict
.get('extended')==None:
2352 raise NfvoException(e_text
+ "After database migration some information is not available. \
2353 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
2355 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
2356 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
2357 netDict
["type"]="virtual"
2358 if "vpci" in iface
and iface
["vpci"] is not None:
2359 netDict
['vpci'] = iface
['vpci']
2360 if "mac" in iface
and iface
["mac"] is not None:
2361 netDict
['mac_address'] = iface
['mac']
2362 if "port-security" in iface
and iface
["port-security"] is not None:
2363 netDict
['port_security'] = iface
['port-security']
2364 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
2365 netDict
['floating_ip'] = iface
['floating-ip']
2366 netDict
['name'] = iface
['internal_name']
2367 if iface
['net_id'] is None:
2368 for vnf_iface
in sce_vnf
["interfaces"]:
2371 if vnf_iface
['interface_id']==iface
['uuid']:
2372 netDict
['net_id'] = auxNetDict
['scenario'][ vnf_iface
['sce_net_id'] ]
2375 netDict
['net_id'] = auxNetDict
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
2376 #skip bridge ifaces not connected to any net
2377 #if 'net_id' not in netDict or netDict['net_id']==None:
2379 myVMDict
['networks'].append(netDict
)
2380 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2381 #print myVMDict['name']
2382 #print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
2383 #print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
2384 #print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
2386 if 'availability_zone' in myVMDict
:
2387 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
2391 vm_id
= myvim
.new_vminstance(myVMDict
['name'], myVMDict
['description'], myVMDict
.get('start', None),
2392 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'],
2393 availability_zone_index
=av_index
,
2394 availability_zone_list
=vnf_availability_zones
)
2395 #print "VIM vm instance id (server id) for scenario %s: %s" % (scenarioDict['name'],vm_id)
2396 vm
['vim_id'] = vm_id
2397 rollbackList
.append({'what':'vm','where':'vim','vim_id':datacenter_id
,'uuid':vm_id
})
2398 #put interface uuid back to scenario[vnfs][vms[[interfaces]
2399 for net
in myVMDict
['networks']:
2401 for iface
in vm
['interfaces']:
2402 if net
["name"]==iface
["internal_name"]:
2403 iface
["vim_id"]=net
["vim_id"]
2406 logger
.debug("start scenario Deployment done")
2407 #print yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False)
2408 #r,c = mydb.new_instance_scenario_as_a_whole(nfvo_tenant,scenarioDict['name'],scenarioDict)
2409 instance_id
= mydb
.new_instance_scenario_as_a_whole(tenant_id
,instance_scenario_name
, instance_scenario_description
, scenarioDict
)
2410 return mydb
.get_instance_scenario(instance_id
)
2412 except (db_base_Exception
, vimconn
.vimconnException
) as e
:
2413 _
, message
= rollback(mydb
, vims
, rollbackList
)
2414 if isinstance(e
, db_base_Exception
):
2415 error_text
= "Exception at database"
2417 error_text
= "Exception at VIM"
2418 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
2419 #logger.error("start_scenario %s", error_text)
2420 raise NfvoException(error_text
, e
.http_code
)
2422 def unify_cloud_config(cloud_config_preserve
, cloud_config
):
2423 """ join the cloud config information into cloud_config_preserve.
2424 In case of conflict cloud_config_preserve preserves
2427 if not cloud_config_preserve
and not cloud_config
:
2430 new_cloud_config
= {"key-pairs":[], "users":[]}
2432 if cloud_config_preserve
:
2433 for key
in cloud_config_preserve
.get("key-pairs", () ):
2434 if key
not in new_cloud_config
["key-pairs"]:
2435 new_cloud_config
["key-pairs"].append(key
)
2437 for key
in cloud_config
.get("key-pairs", () ):
2438 if key
not in new_cloud_config
["key-pairs"]:
2439 new_cloud_config
["key-pairs"].append(key
)
2440 if not new_cloud_config
["key-pairs"]:
2441 del new_cloud_config
["key-pairs"]
2445 new_cloud_config
["users"] += cloud_config
.get("users", () )
2446 if cloud_config_preserve
:
2447 new_cloud_config
["users"] += cloud_config_preserve
.get("users", () )
2448 index_to_delete
= []
2449 users
= new_cloud_config
.get("users", [])
2450 for index0
in range(0,len(users
)):
2451 if index0
in index_to_delete
:
2453 for index1
in range(index0
+1,len(users
)):
2454 if index1
in index_to_delete
:
2456 if users
[index0
]["name"] == users
[index1
]["name"]:
2457 index_to_delete
.append(index1
)
2458 for key
in users
[index1
].get("key-pairs",()):
2459 if "key-pairs" not in users
[index0
]:
2460 users
[index0
]["key-pairs"] = [key
]
2461 elif key
not in users
[index0
]["key-pairs"]:
2462 users
[index0
]["key-pairs"].append(key
)
2463 index_to_delete
.sort(reverse
=True)
2464 for index
in index_to_delete
:
2466 if not new_cloud_config
["users"]:
2467 del new_cloud_config
["users"]
2470 if cloud_config
and cloud_config
.get("boot-data-drive") != None:
2471 new_cloud_config
["boot-data-drive"] = cloud_config
["boot-data-drive"]
2472 if cloud_config_preserve
and cloud_config_preserve
.get("boot-data-drive") != None:
2473 new_cloud_config
["boot-data-drive"] = cloud_config_preserve
["boot-data-drive"]
2476 new_cloud_config
["user-data"] = []
2477 if cloud_config
and cloud_config
.get("user-data"):
2478 if isinstance(cloud_config
["user-data"], list):
2479 new_cloud_config
["user-data"] += cloud_config
["user-data"]
2481 new_cloud_config
["user-data"].append(cloud_config
["user-data"])
2482 if cloud_config_preserve
and cloud_config_preserve
.get("user-data"):
2483 if isinstance(cloud_config_preserve
["user-data"], list):
2484 new_cloud_config
["user-data"] += cloud_config_preserve
["user-data"]
2486 new_cloud_config
["user-data"].append(cloud_config_preserve
["user-data"])
2487 if not new_cloud_config
["user-data"]:
2488 del new_cloud_config
["user-data"]
2491 new_cloud_config
["config-files"] = []
2492 if cloud_config
and cloud_config
.get("config-files") != None:
2493 new_cloud_config
["config-files"] += cloud_config
["config-files"]
2494 if cloud_config_preserve
:
2495 for file in cloud_config_preserve
.get("config-files", ()):
2496 for index
in range(0, len(new_cloud_config
["config-files"])):
2497 if new_cloud_config
["config-files"][index
]["dest"] == file["dest"]:
2498 new_cloud_config
["config-files"][index
] = file
2501 new_cloud_config
["config-files"].append(file)
2502 if not new_cloud_config
["config-files"]:
2503 del new_cloud_config
["config-files"]
2504 return new_cloud_config
2507 def get_vim_thread(mydb
, tenant_id
, datacenter_id_name
=None, datacenter_tenant_id
=None):
2508 datacenter_id
= None
2509 datacenter_name
= None
2512 if datacenter_tenant_id
:
2513 thread_id
= datacenter_tenant_id
2514 thread
= vim_threads
["running"].get(datacenter_tenant_id
)
2516 where_
={"td.nfvo_tenant_id": tenant_id
}
2517 if datacenter_id_name
:
2518 if utils
.check_valid_uuid(datacenter_id_name
):
2519 datacenter_id
= datacenter_id_name
2520 where_
["dt.datacenter_id"] = datacenter_id
2522 datacenter_name
= datacenter_id_name
2523 where_
["d.name"] = datacenter_name
2524 if datacenter_tenant_id
:
2525 where_
["dt.uuid"] = datacenter_tenant_id
2526 datacenters
= mydb
.get_rows(
2527 SELECT
=("dt.uuid as datacenter_tenant_id",),
2528 FROM
="datacenter_tenants as dt join tenants_datacenters as td on dt.uuid=td.datacenter_tenant_id "
2529 "join datacenters as d on d.uuid=dt.datacenter_id",
2531 if len(datacenters
) > 1:
2532 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2534 thread_id
= datacenters
[0]["datacenter_tenant_id"]
2535 thread
= vim_threads
["running"].get(thread_id
)
2537 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2538 return thread_id
, thread
2539 except db_base_Exception
as e
:
2540 raise NfvoException("{} {}".format(type(e
).__name
__ , str(e
)), e
.http_code
)
2543 def get_datacenter_uuid(mydb
, tenant_id
, datacenter_id_name
):
2545 if utils
.check_valid_uuid(datacenter_id_name
):
2546 WHERE_dict
['d.uuid'] = datacenter_id_name
2548 WHERE_dict
['d.name'] = datacenter_id_name
2551 WHERE_dict
['nfvo_tenant_id'] = tenant_id
2552 from_
= "tenants_datacenters as td join datacenters as d on td.datacenter_id=d.uuid join datacenter_tenants as" \
2553 " dt on td.datacenter_tenant_id=dt.uuid"
2555 from_
= 'datacenters as d'
2556 vimaccounts
= mydb
.get_rows(FROM
=from_
, SELECT
=("d.uuid as uuid",), WHERE
=WHERE_dict
)
2557 if len(vimaccounts
) == 0:
2558 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2559 elif len(vimaccounts
)>1:
2560 #print "nfvo.datacenter_action() error. Several datacenters found"
2561 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2562 return vimaccounts
[0]["uuid"]
2565 def get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter_id_name
=None, **extra_filter
):
2566 datacenter_id
= None
2567 datacenter_name
= None
2568 if datacenter_id_name
:
2569 if utils
.check_valid_uuid(datacenter_id_name
):
2570 datacenter_id
= datacenter_id_name
2572 datacenter_name
= datacenter_id_name
2573 vims
= get_vim(mydb
, tenant_id
, datacenter_id
, datacenter_name
, **extra_filter
)
2575 raise NfvoException("datacenter '{}' not found".format(str(datacenter_id_name
)), HTTP_Not_Found
)
2577 #print "nfvo.datacenter_action() error. Several datacenters found"
2578 raise NfvoException("More than one datacenters found, try to identify with uuid", HTTP_Conflict
)
2579 return vims
.keys()[0], vims
.values()[0]
2583 '''Takes dict d and updates it with the values in dict u.'''
2584 '''It merges all depth levels'''
2585 for k
, v
in u
.iteritems():
2586 if isinstance(v
, collections
.Mapping
):
2587 r
= update(d
.get(k
, {}), v
)
2593 def create_instance(mydb
, tenant_id
, instance_dict
):
2594 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
2595 # logger.debug("Creating instance...")
2596 scenario
= instance_dict
["scenario"]
2598 # find main datacenter
2600 myvim_threads_id
= {}
2601 datacenter
= instance_dict
.get("datacenter")
2602 default_datacenter_id
, vim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
2603 myvims
[default_datacenter_id
] = vim
2604 myvim_threads_id
[default_datacenter_id
], _
= get_vim_thread(mydb
, tenant_id
, default_datacenter_id
)
2605 tenant
= mydb
.get_rows_by_id('nfvo_tenants', tenant_id
)
2606 # myvim_tenant = myvim['tenant_id']
2610 # print "Checking that the scenario exists and getting the scenario dictionary"
2611 scenarioDict
= mydb
.get_scenario(scenario
, tenant_id
, datacenter_vim_id
=myvim_threads_id
[default_datacenter_id
],
2612 datacenter_id
=default_datacenter_id
)
2614 # logger.debug(">>>>>> Dictionaries before merging")
2615 # logger.debug(">>>>>> InstanceDict:\n{}".format(yaml.safe_dump(instance_dict,default_flow_style=False, width=256)))
2616 # logger.debug(">>>>>> ScenarioDict:\n{}".format(yaml.safe_dump(scenarioDict,default_flow_style=False, width=256)))
2618 db_instance_vnfs
= []
2619 db_instance_vms
= []
2620 db_instance_interfaces
= []
2625 instance_name
= instance_dict
["name"]
2626 instance_uuid
= str(uuid4())
2627 uuid_list
.append(instance_uuid
)
2628 db_instance_scenario
= {
2629 "uuid": instance_uuid
,
2630 "name": instance_name
,
2631 "tenant_id": tenant_id
,
2632 "scenario_id": scenarioDict
['uuid'],
2633 "datacenter_id": default_datacenter_id
,
2634 # filled bellow 'datacenter_tenant_id'
2635 "description": instance_dict
.get("description"),
2637 if scenarioDict
.get("cloud-config"):
2638 db_instance_scenario
["cloud_config"] = yaml
.safe_dump(scenarioDict
["cloud-config"],
2639 default_flow_style
=True, width
=256)
2640 instance_action_id
= get_task_id()
2641 db_instance_action
= {
2642 "uuid": instance_action_id
, # same uuid for the instance and the action on create
2643 "tenant_id": tenant_id
,
2644 "instance_id": instance_uuid
,
2645 "description": "CREATE",
2648 # Auxiliary dictionaries from x to y
2649 vnf_net2instance
= {}
2650 sce_net2instance
= {}
2651 net2task_id
= {'scenario': {}}
2653 # logger.debug("Creating instance from scenario-dict:\n%s",
2654 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
2656 # 0 check correct parameters
2657 for net_name
, net_instance_desc
in instance_dict
.get("networks", {}).iteritems():
2659 for scenario_net
in scenarioDict
['nets']:
2660 if net_name
== scenario_net
["name"]:
2664 raise NfvoException("Invalid scenario network name '{}' at instance:networks".format(net_name
),
2666 if "sites" not in net_instance_desc
:
2667 net_instance_desc
["sites"] = [ {} ]
2668 site_without_datacenter_field
= False
2669 for site
in net_instance_desc
["sites"]:
2670 if site
.get("datacenter"):
2671 site
["datacenter"] = get_datacenter_uuid(mydb
, tenant_id
, site
["datacenter"])
2672 if site
["datacenter"] not in myvims
:
2673 # Add this datacenter to myvims
2674 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, site
["datacenter"])
2676 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, site
["datacenter"])
2677 site
["datacenter"] = d
# change name to id
2679 if site_without_datacenter_field
:
2680 raise NfvoException("Found more than one entries without datacenter field at "
2681 "instance:networks:{}:sites".format(net_name
), HTTP_Bad_Request
)
2682 site_without_datacenter_field
= True
2683 site
["datacenter"] = default_datacenter_id
# change name to id
2685 for vnf_name
, vnf_instance_desc
in instance_dict
.get("vnfs",{}).iteritems():
2687 for scenario_vnf
in scenarioDict
['vnfs']:
2688 if vnf_name
== scenario_vnf
['name']:
2692 raise NfvoException("Invalid vnf name '{}' at instance:vnfs".format(vnf_instance_desc
), HTTP_Bad_Request
)
2693 if "datacenter" in vnf_instance_desc
:
2694 # Add this datacenter to myvims
2695 vnf_instance_desc
["datacenter"] = get_datacenter_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2696 if vnf_instance_desc
["datacenter"] not in myvims
:
2697 d
, v
= get_datacenter_by_name_uuid(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2699 myvim_threads_id
[d
], _
= get_vim_thread(mydb
, tenant_id
, vnf_instance_desc
["datacenter"])
2700 scenario_vnf
["datacenter"] = vnf_instance_desc
["datacenter"]
2702 # 0.1 parse cloud-config parameters
2703 cloud_config
= unify_cloud_config(instance_dict
.get("cloud-config"), scenarioDict
.get("cloud-config"))
2704 # We add the RO key to cloud_config
2705 if tenant
[0].get('RO_pub_key'):
2706 RO_key
= {"key-pairs": [tenant
[0]['RO_pub_key']]}
2707 cloud_config
= unify_cloud_config(cloud_config
, RO_key
)
2709 # 0.2 merge instance information into scenario
2710 # Ideally, the operation should be as simple as: update(scenarioDict,instance_dict)
2711 # However, this is not possible yet.
2712 for net_name
, net_instance_desc
in instance_dict
.get("networks",{}).iteritems():
2713 for scenario_net
in scenarioDict
['nets']:
2714 if net_name
== scenario_net
["name"]:
2715 if 'ip-profile' in net_instance_desc
:
2716 # translate from input format to database format
2717 ipprofile_in
= net_instance_desc
['ip-profile']
2719 ipprofile_db
['subnet_address'] = ipprofile_in
.get('subnet-address')
2720 ipprofile_db
['ip_version'] = ipprofile_in
.get('ip-version', 'IPv4')
2721 ipprofile_db
['gateway_address'] = ipprofile_in
.get('gateway-address')
2722 ipprofile_db
['dns_address'] = ipprofile_in
.get('dns-address')
2723 if isinstance(ipprofile_db
['dns_address'], (list, tuple)):
2724 ipprofile_db
['dns_address'] = ";".join(ipprofile_db
['dns_address'])
2725 if 'dhcp' in ipprofile_in
:
2726 ipprofile_db
['dhcp_start_address'] = ipprofile_in
['dhcp'].get('start-address')
2727 ipprofile_db
['dhcp_enabled'] = ipprofile_in
['dhcp'].get('enabled', True)
2728 ipprofile_db
['dhcp_count'] = ipprofile_in
['dhcp'].get('count' )
2729 if 'ip_profile' not in scenario_net
:
2730 scenario_net
['ip_profile'] = ipprofile_db
2732 update(scenario_net
['ip_profile'], ipprofile_db
)
2733 for interface
in net_instance_desc
.get('interfaces', () ):
2734 if 'ip_address' in interface
:
2735 for vnf
in scenarioDict
['vnfs']:
2736 if interface
['vnf'] == vnf
['name']:
2737 for vnf_interface
in vnf
['interfaces']:
2738 if interface
['vnf_interface'] == vnf_interface
['external_name']:
2739 vnf_interface
['ip_address']=interface
['ip_address']
2741 # logger.debug(">>>>>>>> Merged dictionary")
2742 # logger.debug("Creating instance scenario-dict MERGED:\n%s",
2743 # yaml.safe_dump(scenarioDict, indent=4, default_flow_style=False))
2745 # 1. Creating new nets (sce_nets) in the VIM"
2746 db_instance_nets
= []
2747 for sce_net
in scenarioDict
['nets']:
2748 descriptor_net
= instance_dict
.get("networks", {}).get(sce_net
["name"], {})
2749 net_name
= descriptor_net
.get("vim-network-name")
2750 sce_net2instance
[sce_net
['uuid']] = {}
2751 net2task_id
['scenario'][sce_net
['uuid']] = {}
2753 sites
= descriptor_net
.get("sites", [ {} ])
2755 if site
.get("datacenter"):
2756 vim
= myvims
[ site
["datacenter"] ]
2757 datacenter_id
= site
["datacenter"]
2758 myvim_thread_id
= myvim_threads_id
[ site
["datacenter"] ]
2760 vim
= myvims
[ default_datacenter_id
]
2761 datacenter_id
= default_datacenter_id
2762 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2763 net_type
= sce_net
['type']
2764 lookfor_filter
= {'admin_state_up': True, 'status': 'ACTIVE'} # 'shared': True
2767 if sce_net
["external"]:
2768 net_name
= sce_net
["name"]
2770 net_name
= "{}.{}".format(instance_name
, sce_net
["name"])
2771 net_name
= net_name
[:255] # limit length
2773 if "netmap-use" in site
or "netmap-create" in site
:
2774 create_network
= False
2775 lookfor_network
= False
2776 if "netmap-use" in site
:
2777 lookfor_network
= True
2778 if utils
.check_valid_uuid(site
["netmap-use"]):
2779 filter_text
= "scenario id '%s'" % site
["netmap-use"]
2780 lookfor_filter
["id"] = site
["netmap-use"]
2782 filter_text
= "scenario name '%s'" % site
["netmap-use"]
2783 lookfor_filter
["name"] = site
["netmap-use"]
2784 if "netmap-create" in site
:
2785 create_network
= True
2786 net_vim_name
= net_name
2787 if site
["netmap-create"]:
2788 net_vim_name
= site
["netmap-create"]
2789 elif sce_net
["external"]:
2790 if sce_net
['vim_id'] != None:
2791 # there is a netmap at datacenter_nets database # TODO REVISE!!!!
2792 create_network
= False
2793 lookfor_network
= True
2794 lookfor_filter
["id"] = sce_net
['vim_id']
2795 filter_text
= "vim_id '{}' datacenter_netmap name '{}'. Try to reload vims with "\
2796 "datacenter-net-update".format(sce_net
['vim_id'], sce_net
["name"])
2797 # look for network at datacenter and return error
2799 # There is not a netmap, look at datacenter for a net with this name and create if not found
2800 create_network
= True
2801 lookfor_network
= True
2802 lookfor_filter
["name"] = sce_net
["name"]
2803 net_vim_name
= sce_net
["name"]
2804 filter_text
= "scenario name '%s'" % sce_net
["name"]
2806 net_vim_name
= net_name
2807 create_network
= True
2808 lookfor_network
= False
2810 if lookfor_network
and create_network
:
2811 # TODO create two tasks FIND + CREATE with their relationship
2812 task_action
= "FIND"
2813 task_params
= (lookfor_filter
,)
2814 # task_action = "CREATE"
2815 # task_params = (net_vim_name, net_type, sce_net.get('ip_profile', None))
2817 elif lookfor_network
:
2818 task_action
= "FIND"
2819 task_params
= (lookfor_filter
,)
2820 elif create_network
:
2821 task_action
= "CREATE"
2822 task_params
= (net_vim_name
, net_type
, sce_net
.get('ip_profile', None))
2824 # fill database content
2825 net_uuid
= str(uuid4())
2826 uuid_list
.append(net_uuid
)
2827 sce_net2instance
[sce_net
['uuid']][datacenter_id
] = net_uuid
2831 "instance_scenario_id": instance_uuid
,
2832 "sce_net_id": sce_net
["uuid"],
2833 "created": create_network
,
2834 'datacenter_id': datacenter_id
,
2835 'datacenter_tenant_id': myvim_thread_id
,
2836 'status': 'BUILD' if create_network
else "ACTIVE"
2838 db_instance_nets
.append(db_net
)
2840 "instance_action_id": instance_action_id
,
2841 "status": "SCHEDULED",
2842 "task_index": task_index
,
2843 "datacenter_vim_id": myvim_thread_id
,
2844 "action": task_action
,
2845 "item": "instance_nets",
2846 "item_id": net_uuid
,
2847 "extra": yaml
.safe_dump({"params": task_params
}, default_flow_style
=True, width
=256)
2849 net2task_id
['scenario'][sce_net
['uuid']][datacenter_id
] = task_index
2851 db_vim_actions
.append(db_vim_action
)
2853 if 'ip_profile' in sce_net
:
2855 'instance_net_id': net_uuid
,
2856 'ip_version': sce_net
['ip_profile']['ip_version'],
2857 'subnet_address': sce_net
['ip_profile']['subnet_address'],
2858 'gateway_address': sce_net
['ip_profile']['gateway_address'],
2859 'dns_address': sce_net
['ip_profile']['dns_address'],
2860 'dhcp_enabled': sce_net
['ip_profile']['dhcp_enabled'],
2861 'dhcp_start_address': sce_net
['ip_profile']['dhcp_start_address'],
2862 'dhcp_count': sce_net
['ip_profile']['dhcp_count'],
2864 db_ip_profiles
.append(db_ip_profile
)
2866 # 2. Creating new nets (vnf internal nets) in the VIM"
2867 # For each vnf net, we create it and we add it to instanceNetlist.
2868 for sce_vnf
in scenarioDict
['vnfs']:
2869 for net
in sce_vnf
['nets']:
2870 if sce_vnf
.get("datacenter"):
2871 datacenter_id
= sce_vnf
["datacenter"]
2872 myvim_thread_id
= myvim_threads_id
[sce_vnf
["datacenter"]]
2874 datacenter_id
= default_datacenter_id
2875 myvim_thread_id
= myvim_threads_id
[default_datacenter_id
]
2876 descriptor_net
= instance_dict
.get("vnfs", {}).get(sce_vnf
["name"], {})
2877 net_name
= descriptor_net
.get("name")
2879 net_name
= "{}.{}".format(instance_name
, net
["name"])
2880 net_name
= net_name
[:255] # limit length
2881 net_type
= net
['type']
2883 if sce_vnf
['uuid'] not in vnf_net2instance
:
2884 vnf_net2instance
[sce_vnf
['uuid']] = {}
2885 if sce_vnf
['uuid'] not in net2task_id
:
2886 net2task_id
[sce_vnf
['uuid']] = {}
2887 net2task_id
[sce_vnf
['uuid']][net
['uuid']] = task_index
2889 # fill database content
2890 net_uuid
= str(uuid4())
2891 uuid_list
.append(net_uuid
)
2892 vnf_net2instance
[sce_vnf
['uuid']][net
['uuid']] = net_uuid
2896 "instance_scenario_id": instance_uuid
,
2897 "net_id": net
["uuid"],
2899 'datacenter_id': datacenter_id
,
2900 'datacenter_tenant_id': myvim_thread_id
,
2902 db_instance_nets
.append(db_net
)
2905 "instance_action_id": instance_action_id
,
2906 "task_index": task_index
,
2907 "datacenter_vim_id": myvim_thread_id
,
2908 "status": "SCHEDULED",
2910 "item": "instance_nets",
2911 "item_id": net_uuid
,
2912 "extra": yaml
.safe_dump({"params": (net_name
, net_type
, net
.get('ip_profile',None))},
2913 default_flow_style
=True, width
=256)
2916 db_vim_actions
.append(db_vim_action
)
2918 if 'ip_profile' in net
:
2920 'instance_net_id': net_uuid
,
2921 'ip_version': net
['ip_profile']['ip_version'],
2922 'subnet_address': net
['ip_profile']['subnet_address'],
2923 'gateway_address': net
['ip_profile']['gateway_address'],
2924 'dns_address': net
['ip_profile']['dns_address'],
2925 'dhcp_enabled': net
['ip_profile']['dhcp_enabled'],
2926 'dhcp_start_address': net
['ip_profile']['dhcp_start_address'],
2927 'dhcp_count': net
['ip_profile']['dhcp_count'],
2929 db_ip_profiles
.append(db_ip_profile
)
2931 # print "vnf_net2instance:"
2932 # print yaml.safe_dump(vnf_net2instance, indent=4, default_flow_style=False)
2934 # 3. Creating new vm instances in the VIM
2935 # myvim.new_vminstance(self,vimURI,tenant_id,name,description,image_id,flavor_id,net_dict)
2936 sce_vnf_list
= sorted(scenarioDict
['vnfs'], key
=lambda k
: k
['name'])
2937 for sce_vnf
in sce_vnf_list
:
2938 vnf_availability_zones
= []
2939 for vm
in sce_vnf
['vms']:
2940 vm_av
= vm
.get('availability_zone')
2941 if vm_av
and vm_av
not in vnf_availability_zones
:
2942 vnf_availability_zones
.append(vm_av
)
2944 # check if there is enough availability zones available at vim level.
2945 if myvims
[datacenter_id
].availability_zone
and vnf_availability_zones
:
2946 if len(vnf_availability_zones
) > len(myvims
[datacenter_id
].availability_zone
):
2947 raise NfvoException('No enough availability zones at VIM for this deployment', HTTP_Bad_Request
)
2949 if sce_vnf
.get("datacenter"):
2950 vim
= myvims
[ sce_vnf
["datacenter"] ]
2951 myvim_thread_id
= myvim_threads_id
[ sce_vnf
["datacenter"] ]
2952 datacenter_id
= sce_vnf
["datacenter"]
2954 vim
= myvims
[ default_datacenter_id
]
2955 myvim_thread_id
= myvim_threads_id
[ default_datacenter_id
]
2956 datacenter_id
= default_datacenter_id
2957 sce_vnf
["datacenter_id"] = datacenter_id
2960 vnf_uuid
= str(uuid4())
2961 uuid_list
.append(vnf_uuid
)
2964 'instance_scenario_id': instance_uuid
,
2965 'vnf_id': sce_vnf
['vnf_id'],
2966 'sce_vnf_id': sce_vnf
['uuid'],
2967 'datacenter_id': datacenter_id
,
2968 'datacenter_tenant_id': myvim_thread_id
,
2970 db_instance_vnfs
.append(db_instance_vnf
)
2972 for vm
in sce_vnf
['vms']:
2974 myVMDict
['name'] = "{}.{}.{}".format(instance_name
[:64], sce_vnf
['name'][:64], vm
["name"][:64])
2975 myVMDict
['description'] = myVMDict
['name'][0:99]
2977 # myVMDict['start'] = "no"
2978 myVMDict
['name'] = myVMDict
['name'][0:255] # limit name length
2979 #create image at vim in case it not exist
2980 image_dict
= mydb
.get_table_by_uuid_name("images", vm
['image_id'])
2981 image_id
= create_or_use_image(mydb
, {datacenter_id
: vim
}, image_dict
, [], True)
2982 vm
['vim_image_id'] = image_id
2984 # create flavor at vim in case it not exist
2985 flavor_dict
= mydb
.get_table_by_uuid_name("flavors", vm
['flavor_id'])
2986 if flavor_dict
['extended']!=None:
2987 flavor_dict
['extended'] = yaml
.load(flavor_dict
['extended'])
2988 flavor_id
= create_or_use_flavor(mydb
, {datacenter_id
: vim
}, flavor_dict
, rollbackList
, True)
2990 # Obtain information for additional disks
2991 extended_flavor_dict
= mydb
.get_rows(FROM
='datacenters_flavors', SELECT
=('extended',), WHERE
={'vim_id': flavor_id
})
2992 if not extended_flavor_dict
:
2993 raise NfvoException("flavor '{}' not found".format(flavor_id
), HTTP_Not_Found
)
2996 # extended_flavor_dict_yaml = yaml.load(extended_flavor_dict[0])
2997 myVMDict
['disks'] = None
2998 extended_info
= extended_flavor_dict
[0]['extended']
2999 if extended_info
!= None:
3000 extended_flavor_dict_yaml
= yaml
.load(extended_info
)
3001 if 'disks' in extended_flavor_dict_yaml
:
3002 myVMDict
['disks'] = extended_flavor_dict_yaml
['disks']
3004 vm
['vim_flavor_id'] = flavor_id
3005 myVMDict
['imageRef'] = vm
['vim_image_id']
3006 myVMDict
['flavorRef'] = vm
['vim_flavor_id']
3007 myVMDict
['availability_zone'] = vm
.get('availability_zone')
3008 myVMDict
['networks'] = []
3009 task_depends_on
= []
3010 # TODO ALF. connect_mgmt_interfaces. Connect management interfaces if this is true
3012 for iface
in vm
['interfaces']:
3014 if iface
['type']=="data":
3015 netDict
['type'] = iface
['model']
3016 elif "model" in iface
and iface
["model"]!=None:
3017 netDict
['model']=iface
['model']
3018 # TODO in future, remove this because mac_address will not be set, and the type of PV,VF
3019 # is obtained from iterface table model
3020 # discover type of interface looking at flavor
3021 for numa
in flavor_dict
.get('extended',{}).get('numas',[]):
3022 for flavor_iface
in numa
.get('interfaces',[]):
3023 if flavor_iface
.get('name') == iface
['internal_name']:
3024 if flavor_iface
['dedicated'] == 'yes':
3025 netDict
['type']="PF" #passthrough
3026 elif flavor_iface
['dedicated'] == 'no':
3027 netDict
['type']="VF" #siov
3028 elif flavor_iface
['dedicated'] == 'yes:sriov':
3029 netDict
['type']="VFnotShared" #sriov but only one sriov on the PF
3030 netDict
["mac_address"] = flavor_iface
.get("mac_address")
3032 netDict
["use"]=iface
['type']
3033 if netDict
["use"]=="data" and not netDict
.get("type"):
3034 #print "netDict", netDict
3035 #print "iface", iface
3036 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'])
3037 if flavor_dict
.get('extended')==None:
3038 raise NfvoException(e_text
+ "After database migration some information is not available. \
3039 Try to delete and create the scenarios and VNFs again", HTTP_Conflict
)
3041 raise NfvoException(e_text
, HTTP_Internal_Server_Error
)
3042 if netDict
["use"]=="mgmt" or netDict
["use"]=="bridge":
3043 netDict
["type"]="virtual"
3044 if "vpci" in iface
and iface
["vpci"] is not None:
3045 netDict
['vpci'] = iface
['vpci']
3046 if "mac" in iface
and iface
["mac"] is not None:
3047 netDict
['mac_address'] = iface
['mac']
3048 if "port-security" in iface
and iface
["port-security"] is not None:
3049 netDict
['port_security'] = iface
['port-security']
3050 if "floating-ip" in iface
and iface
["floating-ip"] is not None:
3051 netDict
['floating_ip'] = iface
['floating-ip']
3052 netDict
['name'] = iface
['internal_name']
3053 if iface
['net_id'] is None:
3054 for vnf_iface
in sce_vnf
["interfaces"]:
3057 if vnf_iface
['interface_id']==iface
['uuid']:
3058 netDict
['net_id'] = "TASK-{}".format(net2task_id
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
])
3059 instance_net_id
= sce_net2instance
[ vnf_iface
['sce_net_id'] ][datacenter_id
]
3060 task_depends_on
.append(net2task_id
['scenario'][ vnf_iface
['sce_net_id'] ][datacenter_id
])
3063 netDict
['net_id'] = "TASK-{}".format(net2task_id
[ sce_vnf
['uuid'] ][ iface
['net_id'] ])
3064 instance_net_id
= vnf_net2instance
[ sce_vnf
['uuid'] ][ iface
['net_id'] ]
3065 task_depends_on
.append(net2task_id
[sce_vnf
['uuid'] ][ iface
['net_id']])
3066 # skip bridge ifaces not connected to any net
3067 if 'net_id' not in netDict
or netDict
['net_id']==None:
3069 myVMDict
['networks'].append(netDict
)
3072 # 'instance_vm_id': instance_vm_uuid,
3073 "instance_net_id": instance_net_id
,
3074 'interface_id': iface
['uuid'],
3075 # 'vim_interface_id': ,
3076 'type': 'external' if iface
['external_name'] is not None else 'internal',
3077 'ip_address': iface
.get('ip_address'),
3078 'floating_ip': int(iface
.get('floating-ip', False)),
3079 'port_security': int(iface
.get('port-security', True))
3081 db_vm_ifaces
.append(db_vm_iface
)
3082 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3083 # print myVMDict['name']
3084 # print "networks", yaml.safe_dump(myVMDict['networks'], indent=4, default_flow_style=False)
3085 # print "interfaces", yaml.safe_dump(vm['interfaces'], indent=4, default_flow_style=False)
3086 # print ">>>>>>>>>>>>>>>>>>>>>>>>>>>"
3087 if vm
.get("boot_data"):
3088 cloud_config_vm
= unify_cloud_config(vm
["boot_data"], cloud_config
)
3090 cloud_config_vm
= cloud_config
3091 if myVMDict
.get('availability_zone'):
3092 av_index
= vnf_availability_zones
.index(myVMDict
['availability_zone'])
3095 for vm_index
in range(0, vm
.get('count', 1)):
3097 if vm
.get('count', 1) > 1:
3098 vm_index_name
+= "." + chr(97 + vm_index
)
3099 task_params
= (myVMDict
['name']+vm_index_name
, myVMDict
['description'], myVMDict
.get('start', None),
3100 myVMDict
['imageRef'], myVMDict
['flavorRef'], myVMDict
['networks'], cloud_config_vm
,
3101 myVMDict
['disks'], av_index
, vnf_availability_zones
)
3102 # put interface uuid back to scenario[vnfs][vms[[interfaces]
3103 for net
in myVMDict
['networks']:
3105 for iface
in vm
['interfaces']:
3106 if net
["name"]==iface
["internal_name"]:
3107 iface
["vim_id"]=net
["vim_id"]
3109 vm_uuid
= str(uuid4())
3110 uuid_list
.append(vm_uuid
)
3113 'instance_vnf_id': vnf_uuid
,
3114 #TODO delete "vim_vm_id": vm_id,
3115 "vm_id": vm
["uuid"],
3118 db_instance_vms
.append(db_vm
)
3121 for db_vm_iface
in db_vm_ifaces
:
3122 iface_uuid
= str(uuid4())
3123 uuid_list
.append(iface_uuid
)
3124 db_vm_iface_instance
= {
3126 "instance_vm_id": vm_uuid
3128 db_vm_iface_instance
.update(db_vm_iface
)
3129 if db_vm_iface_instance
.get("ip_address"): # increment ip_address
3130 ip
= db_vm_iface_instance
.get("ip_address")
3135 ip
= ip
[i
:] + str(int(ip
[:i
]) +1)
3136 db_vm_iface_instance
["ip_address"] = ip
3138 db_vm_iface_instance
["ip_address"] = None
3139 db_instance_interfaces
.append(db_vm_iface_instance
)
3140 myVMDict
['networks'][iface_index
]["uuid"] = iface_uuid
3144 "instance_action_id": instance_action_id
,
3145 "task_index": task_index
,
3146 "datacenter_vim_id": myvim_thread_id
,
3148 "status": "SCHEDULED",
3149 "item": "instance_vms",
3151 "extra": yaml
.safe_dump({"params": task_params
, "depends_on": task_depends_on
},
3152 default_flow_style
=True, width
=256)
3155 db_vim_actions
.append(db_vim_action
)
3157 scenarioDict
["datacenter2tenant"] = myvim_threads_id
3159 db_instance_action
["number_tasks"] = task_index
3160 db_instance_scenario
['datacenter_tenant_id'] = myvim_threads_id
[default_datacenter_id
]
3161 db_instance_scenario
['datacenter_id'] = default_datacenter_id
3163 {"instance_scenarios": db_instance_scenario
},
3164 {"instance_vnfs": db_instance_vnfs
},
3165 {"instance_nets": db_instance_nets
},
3166 {"ip_profiles": db_ip_profiles
},
3167 {"instance_vms": db_instance_vms
},
3168 {"instance_interfaces": db_instance_interfaces
},
3169 {"instance_actions": db_instance_action
},
3170 {"vim_actions": db_vim_actions
}
3173 logger
.debug("create_instance done DB tables: %s",
3174 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False) )
3175 mydb
.new_rows(db_tables
, uuid_list
)
3176 for myvim_thread_id
in myvim_threads_id
.values():
3177 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3179 returned_instance
= mydb
.get_instance_scenario(instance_uuid
)
3180 returned_instance
["action_id"] = instance_action_id
3181 return returned_instance
3182 except (NfvoException
, vimconn
.vimconnException
, db_base_Exception
) as e
:
3183 message
= rollback(mydb
, myvims
, rollbackList
)
3184 if isinstance(e
, db_base_Exception
):
3185 error_text
= "database Exception"
3186 elif isinstance(e
, vimconn
.vimconnException
):
3187 error_text
= "VIM Exception"
3189 error_text
= "Exception"
3190 error_text
+= " {} {}. {}".format(type(e
).__name
__, str(e
), message
)
3191 # logger.error("create_instance: %s", error_text)
3192 raise NfvoException(error_text
, e
.http_code
)
3195 def delete_instance(mydb
, tenant_id
, instance_id
):
3196 # print "Checking that the instance_id exists and getting the instance dictionary"
3197 instanceDict
= mydb
.get_instance_scenario(instance_id
, tenant_id
)
3198 # print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
3199 tenant_id
= instanceDict
["tenant_id"]
3200 # print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3202 # 1. Delete from Database
3203 message
= mydb
.delete_instance_scenario(instance_id
, tenant_id
)
3205 # 2. delete from VIM
3209 vimthread_affected
= {}
3212 instance_action_id
= get_task_id()
3214 db_instance_action
= {
3215 "uuid": instance_action_id
, # same uuid for the instance and the action on create
3216 "tenant_id": tenant_id
,
3217 "instance_id": instance_id
,
3218 "description": "DELETE",
3219 # "number_tasks": 0 # filled bellow
3224 for sce_vnf
in instanceDict
['vnfs']:
3225 datacenter_key
= (sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3226 vimthread_affected
[sce_vnf
["datacenter_tenant_id"]] = None
3227 if datacenter_key
not in myvims
:
3229 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3230 except NfvoException
as e
:
3231 logger
.error(str(e
))
3233 myvim_threads
[datacenter_key
] = myvim_thread
3234 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=sce_vnf
["datacenter_id"],
3235 datacenter_tenant_id
=sce_vnf
["datacenter_tenant_id"])
3237 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf
["datacenter_id"],
3238 sce_vnf
["datacenter_tenant_id"]))
3239 myvims
[datacenter_key
] = None
3241 myvims
[datacenter_key
] = vims
.values()[0]
3242 myvim
= myvims
[datacenter_key
]
3243 myvim_thread
= myvim_threads
[datacenter_key
]
3244 for vm
in sce_vnf
['vms']:
3246 error_msg
+= "\n VM id={} cannot be deleted because datacenter={} not found".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
3250 "instance_action_id": instance_action_id
,
3251 "task_index": task_index
,
3252 "datacenter_vim_id": sce_vnf
["datacenter_tenant_id"],
3254 "status": "SCHEDULED",
3255 "item": "instance_vms",
3256 "item_id": vm
["uuid"],
3257 "extra": yaml
.safe_dump({"params": vm
["interfaces"]},
3258 default_flow_style
=True, width
=256)
3261 db_vim_actions
.append(db_vim_action
)
3263 except vimconn
.vimconnNotFoundException
as e
:
3264 error_msg
+="\n VM VIM_id={} not found at datacenter={}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"])
3265 logger
.warn("VM instance '%s'uuid '%s', VIM id '%s', from VNF_id '%s' not found",
3266 vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'])
3267 except vimconn
.vimconnException
as e
:
3268 error_msg
+="\n VM VIM_id={} at datacenter={} Error: {} {}".format(vm
['vim_vm_id'], sce_vnf
["datacenter_id"], e
.http_code
, str(e
))
3269 logger
.error("Error %d deleting VM instance '%s'uuid '%s', VIM_id '%s', from VNF_id '%s': %s",
3270 e
.http_code
, vm
['name'], vm
['uuid'], vm
['vim_vm_id'], sce_vnf
['vnf_id'], str(e
))
3274 for net
in instanceDict
['nets']:
3275 # TODO if not net['created']:
3276 # TODO continue #skip not created nets
3278 vimthread_affected
[net
["datacenter_tenant_id"]] = None
3279 datacenter_key
= (net
["datacenter_id"], net
["datacenter_tenant_id"])
3280 if datacenter_key
not in myvims
:
3282 _
,myvim_thread
= get_vim_thread(mydb
, tenant_id
, sce_vnf
["datacenter_id"], sce_vnf
["datacenter_tenant_id"])
3283 except NfvoException
as e
:
3284 logger
.error(str(e
))
3286 myvim_threads
[datacenter_key
] = myvim_thread
3287 vims
= get_vim(mydb
, tenant_id
, datacenter_id
=net
["datacenter_id"],
3288 datacenter_tenant_id
=net
["datacenter_tenant_id"])
3290 logger
.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net
["datacenter_id"], net
["datacenter_tenant_id"]))
3291 myvims
[datacenter_key
] = None
3293 myvims
[datacenter_key
] = vims
.values()[0]
3294 myvim
= myvims
[datacenter_key
]
3295 myvim_thread
= myvim_threads
[datacenter_key
]
3298 error_msg
+= "\n Net VIM_id={} cannot be deleted because datacenter={} not found".format(net
['vim_net_id'], net
["datacenter_id"])
3302 "instance_action_id": instance_action_id
,
3303 "task_index": task_index
,
3304 "datacenter_vim_id": net
["datacenter_tenant_id"],
3306 "status": "SCHEDULED",
3307 "item": "instance_nets",
3308 "item_id": net
["uuid"],
3309 "extra": yaml
.safe_dump({"params": (net
['vim_net_id'], net
['sdn_net_id'])},
3310 default_flow_style
=True, width
=256)
3313 db_vim_actions
.append(db_vim_action
)
3315 except vimconn
.vimconnNotFoundException
as e
:
3316 error_msg
+= "\n NET VIM_id={} not found at datacenter={}".format(net
['vim_net_id'], net
["datacenter_id"])
3317 logger
.warn("NET '%s', VIM_id '%s', from VNF_net_id '%s' not found",
3318 net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']))
3319 except vimconn
.vimconnException
as e
:
3320 error_msg
+= "\n NET VIM_id={} at datacenter={} Error: {} {}".format(net
['vim_net_id'],
3321 net
["datacenter_id"],
3322 e
.http_code
, str(e
))
3323 logger
.error("Error %d deleting NET '%s', VIM_id '%s', from VNF_net_id '%s': %s",
3324 e
.http_code
, net
['uuid'], net
['vim_net_id'], str(net
['vnf_net_id']), str(e
))
3326 db_instance_action
["number_tasks"] = task_index
3328 {"instance_actions": db_instance_action
},
3329 {"vim_actions": db_vim_actions
}
3332 logger
.debug("delete_instance done DB tables: %s",
3333 yaml
.safe_dump(db_tables
, indent
=4, default_flow_style
=False))
3334 mydb
.new_rows(db_tables
, ())
3335 for myvim_thread_id
in vimthread_affected
.keys():
3336 vim_threads
["running"][myvim_thread_id
].insert_task(db_vim_actions
)
3338 if len(error_msg
) > 0:
3339 return 'action_id={} instance {} deleted but some elements could not be deleted, or already deleted '\
3340 '(error: 404) from VIM: {}'.format(instance_action_id
, message
, error_msg
)
3342 return "action_id={} instance {} deleted".format(instance_action_id
, message
)
3345 def refresh_instance(mydb
, nfvo_tenant
, instanceDict
, datacenter
=None, vim_tenant
=None):
3346 '''Refreshes a scenario instance. It modifies instanceDict'''
3348 - 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
3351 # # Assumption: nfvo_tenant and instance_id were checked before entering into this function
3352 # #print "nfvo.refresh_instance begins"
3353 # #print json.dumps(instanceDict, indent=4)
3355 # #print "Getting the VIM URL and the VIM tenant_id"
3358 # # 1. Getting VIM vm and net list
3359 # vms_updated = [] #List of VM instance uuids in openmano that were updated
3362 # for sce_vnf in instanceDict['vnfs']:
3363 # datacenter_key = (sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"])
3364 # if datacenter_key not in vm_list:
3365 # vm_list[datacenter_key] = []
3366 # if datacenter_key not in myvims:
3367 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=sce_vnf["datacenter_id"],
3368 # datacenter_tenant_id=sce_vnf["datacenter_tenant_id"])
3369 # if len(vims) == 0:
3370 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(sce_vnf["datacenter_id"], sce_vnf["datacenter_tenant_id"]))
3371 # myvims[datacenter_key] = None
3373 # myvims[datacenter_key] = vims.values()[0]
3374 # for vm in sce_vnf['vms']:
3375 # vm_list[datacenter_key].append(vm['vim_vm_id'])
3376 # vms_notupdated.append(vm["uuid"])
3378 # nets_updated = [] #List of VM instance uuids in openmano that were updated
3379 # nets_notupdated=[]
3381 # for net in instanceDict['nets']:
3382 # datacenter_key = (net["datacenter_id"], net["datacenter_tenant_id"])
3383 # if datacenter_key not in net_list:
3384 # net_list[datacenter_key] = []
3385 # if datacenter_key not in myvims:
3386 # vims = get_vim(mydb, nfvo_tenant, datacenter_id=net["datacenter_id"],
3387 # datacenter_tenant_id=net["datacenter_tenant_id"])
3388 # if len(vims) == 0:
3389 # logger.error("datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"]))
3390 # myvims[datacenter_key] = None
3392 # myvims[datacenter_key] = vims.values()[0]
3394 # net_list[datacenter_key].append(net['vim_net_id'])
3395 # nets_notupdated.append(net["uuid"])
3397 # # 1. Getting the status of all VMs
3399 # for datacenter_key in myvims:
3400 # if not vm_list.get(datacenter_key):
3404 # if not myvims[datacenter_key]:
3405 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
3408 # vm_dict.update(myvims[datacenter_key].refresh_vms_status(vm_list[datacenter_key]) )
3410 # except vimconn.vimconnException as e:
3411 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
3412 # failed_message = str(e)
3414 # for vm in vm_list[datacenter_key]:
3415 # vm_dict[vm] = {'status': "VIM_ERROR", 'error_msg': failed_message}
3417 # # 2. Update the status of VMs in the instanceDict, while collects the VMs whose status changed
3418 # for sce_vnf in instanceDict['vnfs']:
3419 # for vm in sce_vnf['vms']:
3420 # vm_id = vm['vim_vm_id']
3421 # interfaces = vm_dict[vm_id].pop('interfaces', [])
3422 # #2.0 look if contain manamgement interface, and if not change status from ACTIVE:NoMgmtIP to ACTIVE
3423 # has_mgmt_iface = False
3424 # for iface in vm["interfaces"]:
3425 # if iface["type"]=="mgmt":
3426 # has_mgmt_iface = True
3427 # if vm_dict[vm_id]['status'] == "ACTIVE:NoMgmtIP" and not has_mgmt_iface:
3428 # vm_dict[vm_id]['status'] = "ACTIVE"
3429 # if vm_dict[vm_id].get('error_msg') and len(vm_dict[vm_id]['error_msg']) >= 1024:
3430 # vm_dict[vm_id]['error_msg'] = vm_dict[vm_id]['error_msg'][:516] + " ... " + vm_dict[vm_id]['error_msg'][-500:]
3431 # 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'):
3432 # vm['status'] = vm_dict[vm_id]['status']
3433 # vm['error_msg'] = vm_dict[vm_id].get('error_msg')
3434 # vm['vim_info'] = vm_dict[vm_id].get('vim_info')
3435 # # 2.1. Update in openmano DB the VMs whose status changed
3437 # updates = mydb.update_rows('instance_vms', UPDATE=vm_dict[vm_id], WHERE={'uuid':vm["uuid"]})
3438 # vms_notupdated.remove(vm["uuid"])
3440 # vms_updated.append(vm["uuid"])
3441 # except db_base_Exception as e:
3442 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
3443 # # 2.2. Update in openmano DB the interface VMs
3444 # for interface in interfaces:
3445 # #translate from vim_net_id to instance_net_id
3446 # network_id_list=[]
3447 # for net in instanceDict['nets']:
3448 # if net["vim_net_id"] == interface["vim_net_id"]:
3449 # network_id_list.append(net["uuid"])
3450 # if not network_id_list:
3452 # del interface["vim_net_id"]
3454 # for network_id in network_id_list:
3455 # mydb.update_rows('instance_interfaces', UPDATE=interface, WHERE={'instance_vm_id':vm["uuid"], "instance_net_id":network_id})
3456 # except db_base_Exception as e:
3457 # logger.error( "nfvo.refresh_instance error with vm=%s, interface_net_id=%s", vm["uuid"], network_id)
3459 # # 3. Getting the status of all nets
3461 # for datacenter_key in myvims:
3462 # if not net_list.get(datacenter_key):
3465 # failed_message = ""
3466 # if not myvims[datacenter_key]:
3467 # failed_message = "datacenter '{}' with datacenter_tenant_id '{}' not found".format(net["datacenter_id"], net["datacenter_tenant_id"])
3470 # net_dict.update(myvims[datacenter_key].refresh_nets_status(net_list[datacenter_key]) )
3472 # except vimconn.vimconnException as e:
3473 # logger.error("VIM exception %s %s", type(e).__name__, str(e))
3474 # failed_message = str(e)
3476 # for net in net_list[datacenter_key]:
3477 # net_dict[net] = {'status': "VIM_ERROR", 'error_msg': failed_message}
3479 # # 4. Update the status of nets in the instanceDict, while collects the nets whose status changed
3480 # # TODO: update nets inside a vnf
3481 # for net in instanceDict['nets']:
3482 # net_id = net['vim_net_id']
3483 # if net_dict[net_id].get('error_msg') and len(net_dict[net_id]['error_msg']) >= 1024:
3484 # net_dict[net_id]['error_msg'] = net_dict[net_id]['error_msg'][:516] + " ... " + net_dict[vm_id]['error_msg'][-500:]
3485 # 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'):
3486 # net['status'] = net_dict[net_id]['status']
3487 # net['error_msg'] = net_dict[net_id].get('error_msg')
3488 # net['vim_info'] = net_dict[net_id].get('vim_info')
3489 # # 5.1. Update in openmano DB the nets whose status changed
3491 # updated = mydb.update_rows('instance_nets', UPDATE=net_dict[net_id], WHERE={'uuid':net["uuid"]})
3492 # nets_notupdated.remove(net["uuid"])
3494 # nets_updated.append(net["uuid"])
3495 # except db_base_Exception as e:
3496 # logger.error("nfvo.refresh_instance error database update: %s", str(e))
3498 # # Returns appropriate output
3499 # #print "nfvo.refresh_instance finishes"
3500 # logger.debug("VMs updated in the database: %s; nets updated in the database %s; VMs not updated: %s; nets not updated: %s",
3501 # str(vms_updated), str(nets_updated), str(vms_notupdated), str(nets_notupdated))
3502 instance_id
= instanceDict
['uuid']
3503 # if len(vms_notupdated)+len(nets_notupdated)>0:
3504 # error_msg = "VMs not updated: " + str(vms_notupdated) + "; nets not updated: " + str(nets_notupdated)
3505 # return len(vms_notupdated)+len(nets_notupdated), 'Scenario instance ' + instance_id + ' refreshed but some elements could not be updated in the database: ' + error_msg
3507 return 0, 'Scenario instance ' + instance_id
+ ' refreshed.'
3509 def instance_action(mydb
,nfvo_tenant
,instance_id
, action_dict
):
3510 #print "Checking that the instance_id exists and getting the instance dictionary"
3511 instanceDict
= mydb
.get_instance_scenario(instance_id
, nfvo_tenant
)
3512 #print yaml.safe_dump(instanceDict, indent=4, default_flow_style=False)
3514 #print "Checking that nfvo_tenant_id exists and getting the VIM URI and the VIM tenant_id"
3515 vims
= get_vim(mydb
, nfvo_tenant
, instanceDict
['datacenter_id'])
3517 raise NfvoException("datacenter '{}' not found".format(str(instanceDict
['datacenter_id'])), HTTP_Not_Found
)
3518 myvim
= vims
.values()[0]
3520 if action_dict
.get("create-vdu"):
3521 for vdu
in action_dict
["create-vdu"]:
3522 vdu_id
= vdu
.get("vdu-id")
3523 vdu_count
= vdu
.get("count", 1)
3524 # get from database TODO
3528 input_vnfs
= action_dict
.pop("vnfs", [])
3529 input_vms
= action_dict
.pop("vms", [])
3530 action_over_all
= True if len(input_vnfs
)==0 and len (input_vms
)==0 else False
3534 for sce_vnf
in instanceDict
['vnfs']:
3535 for vm
in sce_vnf
['vms']:
3536 if not action_over_all
:
3537 if sce_vnf
['uuid'] not in input_vnfs
and sce_vnf
['vnf_name'] not in input_vnfs
and \
3538 vm
['uuid'] not in input_vms
and vm
['name'] not in input_vms
:
3541 if "add_public_key" in action_dict
:
3543 if sce_vnf
.get('mgmt_access'):
3544 mgmt_access
= yaml
.load(sce_vnf
['mgmt_access'])
3545 ssh_access
= mgmt_access
['config-access']['ssh-access']
3546 tenant
= mydb
.get_rows_by_id('nfvo_tenants', nfvo_tenant
)
3548 if ssh_access
['required'] and ssh_access
['default-user']:
3549 if 'ip_address' in vm
:
3550 mgmt_ip
= vm
['ip_address'].split(';')
3551 password
= mgmt_access
['config-access'].get('password')
3552 priv_RO_key
= decrypt_key(tenant
[0]['encrypted_RO_priv_key'], tenant
[0]['uuid'])
3553 myvim
.inject_user_key(mgmt_ip
[0], ssh_access
['default-user'],
3554 action_dict
['add_public_key'],
3555 password
=password
, ro_key
=priv_RO_key
)
3557 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
3558 HTTP_Internal_Server_Error
)
3560 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
3561 HTTP_Internal_Server_Error
)
3563 raise NfvoException("Unable to inject ssh key in vm: {} - Aborting".format(vm
['uuid']),
3564 HTTP_Internal_Server_Error
)
3566 data
= myvim
.action_vminstance(vm
['vim_vm_id'], action_dict
)
3567 if "console" in action_dict
:
3568 if not global_config
["http_console_proxy"]:
3569 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
3570 "description": "{protocol}//{ip}:{port}/{suffix}".format(
3571 protocol
=data
["protocol"],
3572 ip
= data
["server"],
3573 port
= data
["port"],
3574 suffix
= data
["suffix"]),
3578 elif data
["server"]=="127.0.0.1" or data
["server"]=="localhost":
3579 vm_result
[ vm
['uuid'] ] = {"vim_result": -HTTP_Unauthorized
,
3580 "description": "this console is only reachable by local interface",
3585 #print "console data", data
3587 console_thread
= create_or_use_console_proxy_thread(data
["server"], data
["port"])
3588 vm_result
[ vm
['uuid'] ] = {"vim_result": 200,
3589 "description": "{protocol}//{ip}:{port}/{suffix}".format(
3590 protocol
=data
["protocol"],
3591 ip
= global_config
["http_console_host"],
3592 port
= console_thread
.port
,
3593 suffix
= data
["suffix"]),
3597 except NfvoException
as e
:
3598 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
3602 vm_result
[ vm
['uuid'] ] = {"vim_result": 200, "description": "ok", "name":vm
['name']}
3604 except vimconn
.vimconnException
as e
:
3605 vm_result
[ vm
['uuid'] ] = {"vim_result": e
.http_code
, "name":vm
['name'], "description": str(e
)}
3608 if vm_ok
==0: #all goes wrong
3613 def instance_action_get(mydb
, nfvo_tenant
, instance_id
, action_id
):
3615 if nfvo_tenant
and nfvo_tenant
!= "any":
3616 filter["tenant_id"] = nfvo_tenant
3617 if instance_id
and instance_id
!= "any":
3618 filter["instance_id"] = instance_id
3620 filter["uuid"] = action_id
3621 rows
= mydb
.get_rows(FROM
="instance_actions", WHERE
=filter)
3622 if not rows
and action_id
:
3623 raise NfvoException("Not found any action with this criteria", HTTP_Not_Found
)
3624 return {"ations": rows
}
3627 def create_or_use_console_proxy_thread(console_server
, console_port
):
3628 #look for a non-used port
3629 console_thread_key
= console_server
+ ":" + str(console_port
)
3630 if console_thread_key
in global_config
["console_thread"]:
3631 #global_config["console_thread"][console_thread_key].start_timeout()
3632 return global_config
["console_thread"][console_thread_key
]
3634 for port
in global_config
["console_port_iterator"]():
3635 #print "create_or_use_console_proxy_thread() port:", port
3636 if port
in global_config
["console_ports"]:
3639 clithread
= cli
.ConsoleProxyThread(global_config
['http_host'], port
, console_server
, console_port
)
3641 global_config
["console_thread"][console_thread_key
] = clithread
3642 global_config
["console_ports"][port
] = console_thread_key
3644 except cli
.ConsoleProxyExceptionPortUsed
as e
:
3645 #port used, try with onoher
3647 except cli
.ConsoleProxyException
as e
:
3648 raise NfvoException(str(e
), HTTP_Bad_Request
)
3649 raise NfvoException("Not found any free 'http_console_ports'", HTTP_Conflict
)
3652 def check_tenant(mydb
, tenant_id
):
3653 '''check that tenant exists at database'''
3654 tenant
= mydb
.get_rows(FROM
='nfvo_tenants', SELECT
=('uuid',), WHERE
={'uuid': tenant_id
})
3656 raise NfvoException("tenant '{}' not found".format(tenant_id
), HTTP_Not_Found
)
3659 def new_tenant(mydb
, tenant_dict
):
3661 tenant_uuid
= str(uuid4())
3662 tenant_dict
['uuid'] = tenant_uuid
3664 pub_key
, priv_key
= create_RO_keypair(tenant_uuid
)
3665 tenant_dict
['RO_pub_key'] = pub_key
3666 tenant_dict
['encrypted_RO_priv_key'] = priv_key
3667 mydb
.new_row("nfvo_tenants", tenant_dict
, confidential_data
=True)
3668 except db_base_Exception
as e
:
3669 raise NfvoException("Error creating the new tenant: {} ".format(tenant_dict
['name']) + str(e
), HTTP_Internal_Server_Error
)
3672 def delete_tenant(mydb
, tenant
):
3673 #get nfvo_tenant info
3675 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant
, 'tenant')
3676 mydb
.delete_row_by_id("nfvo_tenants", tenant_dict
['uuid'])
3677 return tenant_dict
['uuid'] + " " + tenant_dict
["name"]
3680 def new_datacenter(mydb
, datacenter_descriptor
):
3681 if "config" in datacenter_descriptor
:
3682 datacenter_descriptor
["config"]=yaml
.safe_dump(datacenter_descriptor
["config"],default_flow_style
=True,width
=256)
3683 #Check that datacenter-type is correct
3684 datacenter_type
= datacenter_descriptor
.get("type", "openvim");
3687 module
= "vimconn_" + datacenter_type
3688 pkg
= __import__("osm_ro." + module
)
3689 vim_conn
= getattr(pkg
, module
)
3690 # module_info = imp.find_module(module, [__file__[:__file__.rfind("/")]])
3691 except (IOError, ImportError):
3692 # if module_info and module_info[0]:
3693 # file.close(module_info[0])
3694 raise NfvoException("Incorrect datacenter type '{}'. Plugin '{}'.py not installed".format(datacenter_type
, module
), HTTP_Bad_Request
)
3696 datacenter_id
= mydb
.new_row("datacenters", datacenter_descriptor
, add_uuid
=True, confidential_data
=True)
3697 return datacenter_id
3700 def edit_datacenter(mydb
, datacenter_id_name
, datacenter_descriptor
):
3701 # obtain data, check that only one exist
3702 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id_name
)
3705 datacenter_id
= datacenter
['uuid']
3706 where
={'uuid': datacenter
['uuid']}
3707 remove_port_mapping
= False
3708 if "config" in datacenter_descriptor
:
3709 if datacenter_descriptor
['config'] != None:
3711 new_config_dict
= datacenter_descriptor
["config"]
3714 for k
in new_config_dict
:
3715 if new_config_dict
[k
] == None:
3717 if k
== 'sdn-controller':
3718 remove_port_mapping
= True
3720 config_text
= datacenter
.get("config")
3723 config_dict
= yaml
.load(config_text
)
3724 config_dict
.update(new_config_dict
)
3728 except Exception as e
:
3729 raise NfvoException("Bad format at datacenter:config " + str(e
), HTTP_Bad_Request
)
3731 datacenter_descriptor
["config"] = yaml
.safe_dump(config_dict
, default_flow_style
=True, width
=256)
3733 datacenter_descriptor
["config"] = None
3734 if remove_port_mapping
:
3736 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_id
)
3737 except ovimException
as e
:
3738 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
3740 mydb
.update_rows('datacenters', datacenter_descriptor
, where
)
3741 return datacenter_id
3744 def delete_datacenter(mydb
, datacenter
):
3745 #get nfvo_tenant info
3746 datacenter_dict
= mydb
.get_table_by_uuid_name('datacenters', datacenter
, 'datacenter')
3747 mydb
.delete_row_by_id("datacenters", datacenter_dict
['uuid'])
3749 datacenter_sdn_port_mapping_delete(mydb
, None, datacenter_dict
['uuid'])
3750 except ovimException
as e
:
3751 logger
.error("Error deleting datacenter-port-mapping " + str(e
))
3752 return datacenter_dict
['uuid'] + " " + datacenter_dict
['name']
3755 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):
3756 # get datacenter info
3757 datacenter_id
= get_datacenter_uuid(mydb
, None, datacenter
)
3759 create_vim_tenant
= True if not vim_tenant_id
and not vim_tenant_name
else False
3761 # get nfvo_tenant info
3762 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', nfvo_tenant
)
3763 if vim_tenant_name
==None:
3764 vim_tenant_name
=tenant_dict
['name']
3766 #check that this association does not exist before
3767 tenants_datacenter_dict
={"nfvo_tenant_id":tenant_dict
['uuid'], "datacenter_id":datacenter_id
}
3768 tenants_datacenters
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3769 if len(tenants_datacenters
)>0:
3770 raise NfvoException("datacenter '{}' and tenant'{}' are already attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Conflict
)
3772 vim_tenant_id_exist_atdb
=False
3773 if not create_vim_tenant
:
3774 where_
={"datacenter_id": datacenter_id
}
3775 if vim_tenant_id
!=None:
3776 where_
["vim_tenant_id"] = vim_tenant_id
3777 if vim_tenant_name
!=None:
3778 where_
["vim_tenant_name"] = vim_tenant_name
3779 #check if vim_tenant_id is already at database
3780 datacenter_tenants_dict
= mydb
.get_rows(FROM
='datacenter_tenants', WHERE
=where_
)
3781 if len(datacenter_tenants_dict
)>=1:
3782 datacenter_tenants_dict
= datacenter_tenants_dict
[0]
3783 vim_tenant_id_exist_atdb
=True
3784 #TODO check if a field has changed and edit entry at datacenter_tenants at DB
3786 datacenter_tenants_dict
= {}
3787 #insert at table datacenter_tenants
3788 else: #if vim_tenant_id==None:
3789 #create tenant at VIM if not provided
3791 _
, myvim
= get_datacenter_by_name_uuid(mydb
, None, datacenter
, vim_user
=vim_username
,
3792 vim_passwd
=vim_password
)
3793 datacenter_name
= myvim
["name"]
3794 vim_tenant_id
= myvim
.new_tenant(vim_tenant_name
, "created by openmano for datacenter "+datacenter_name
)
3795 except vimconn
.vimconnException
as e
:
3796 raise NfvoException("Not possible to create vim_tenant {} at VIM: {}".format(vim_tenant_id
, str(e
)), HTTP_Internal_Server_Error
)
3797 datacenter_tenants_dict
= {}
3798 datacenter_tenants_dict
["created"]="true"
3800 #fill datacenter_tenants table
3801 if not vim_tenant_id_exist_atdb
:
3802 datacenter_tenants_dict
["vim_tenant_id"] = vim_tenant_id
3803 datacenter_tenants_dict
["vim_tenant_name"] = vim_tenant_name
3804 datacenter_tenants_dict
["user"] = vim_username
3805 datacenter_tenants_dict
["passwd"] = vim_password
3806 datacenter_tenants_dict
["datacenter_id"] = datacenter_id
3808 datacenter_tenants_dict
["config"] = yaml
.safe_dump(config
, default_flow_style
=True, width
=256)
3809 id_
= mydb
.new_row('datacenter_tenants', datacenter_tenants_dict
, add_uuid
=True, confidential_data
=True)
3810 datacenter_tenants_dict
["uuid"] = id_
3812 #fill tenants_datacenters table
3813 datacenter_tenant_id
= datacenter_tenants_dict
["uuid"]
3814 tenants_datacenter_dict
["datacenter_tenant_id"] = datacenter_tenant_id
3815 mydb
.new_row('tenants_datacenters', tenants_datacenter_dict
)
3817 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_dict
['uuid'], datacenter_id
) # reload data
3818 datacenter_name
= myvim
["name"]
3819 thread_name
= get_non_used_vim_name(datacenter_name
, datacenter_id
, tenant_dict
['name'], tenant_dict
['uuid'])
3820 new_thread
= vim_thread
.vim_thread(myvim
, task_lock
, thread_name
, datacenter_name
, datacenter_tenant_id
,
3821 db
=db
, db_lock
=db_lock
, ovim
=ovim
)
3823 thread_id
= datacenter_tenants_dict
["uuid"]
3824 vim_threads
["running"][thread_id
] = new_thread
3825 return datacenter_id
3828 def edit_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=None, vim_tenant_name
=None,
3829 vim_username
=None, vim_password
=None, config
=None):
3830 #Obtain the data of this datacenter_tenant_id
3831 vim_data
= mydb
.get_rows(
3832 SELECT
=("datacenter_tenants.vim_tenant_name", "datacenter_tenants.vim_tenant_id", "datacenter_tenants.user",
3833 "datacenter_tenants.passwd", "datacenter_tenants.config"),
3834 FROM
="datacenter_tenants JOIN tenants_datacenters ON datacenter_tenants.uuid=tenants_datacenters.datacenter_tenant_id",
3835 WHERE
={"tenants_datacenters.nfvo_tenant_id": nfvo_tenant
,
3836 "tenants_datacenters.datacenter_id": datacenter_id
})
3838 logger
.debug(str(vim_data
))
3839 if len(vim_data
) < 1:
3840 raise NfvoException("Datacenter {} is not attached for tenant {}".format(datacenter_id
, nfvo_tenant
), HTTP_Conflict
)
3844 v
['config'] = yaml
.load(v
['config'])
3847 v
['vim_tenant_id'] = vim_tenant_id
3849 v
['vim_tenant_name'] = vim_tenant_name
3851 v
['user'] = vim_username
3853 v
['passwd'] = vim_password
3857 v
['config'].update(config
)
3859 logger
.debug(str(v
))
3860 deassociate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'])
3861 associate_datacenter_to_tenant(mydb
, nfvo_tenant
, datacenter_id
, vim_tenant_id
=v
['vim_tenant_id'], vim_tenant_name
=v
['vim_tenant_name'],
3862 vim_username
=v
['user'], vim_password
=v
['passwd'], config
=v
['config'])
3864 return datacenter_id
3866 def deassociate_datacenter_to_tenant(mydb
, tenant_id
, datacenter
, vim_tenant_id
=None):
3867 #get datacenter info
3868 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3870 #get nfvo_tenant info
3871 if not tenant_id
or tenant_id
=="any":
3874 tenant_dict
= mydb
.get_table_by_uuid_name('nfvo_tenants', tenant_id
)
3875 tenant_uuid
= tenant_dict
['uuid']
3877 #check that this association exist before
3878 tenants_datacenter_dict
={"datacenter_id":datacenter_id
}
3880 tenants_datacenter_dict
["nfvo_tenant_id"] = tenant_uuid
3881 tenant_datacenter_list
= mydb
.get_rows(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3882 if len(tenant_datacenter_list
)==0 and tenant_uuid
:
3883 raise NfvoException("datacenter '{}' and tenant '{}' are not attached".format(datacenter_id
, tenant_dict
['uuid']), HTTP_Not_Found
)
3885 #delete this association
3886 mydb
.delete_row(FROM
='tenants_datacenters', WHERE
=tenants_datacenter_dict
)
3888 #get vim_tenant info and deletes
3890 for tenant_datacenter_item
in tenant_datacenter_list
:
3891 vim_tenant_dict
= mydb
.get_table_by_uuid_name('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
3892 #try to delete vim:tenant
3894 mydb
.delete_row_by_id('datacenter_tenants', tenant_datacenter_item
['datacenter_tenant_id'])
3895 if vim_tenant_dict
['created']=='true':
3896 #delete tenant at VIM if created by NFVO
3898 myvim
.delete_tenant(vim_tenant_dict
['vim_tenant_id'])
3899 except vimconn
.vimconnException
as e
:
3900 warning
= "Not possible to delete vim_tenant_id {} from VIM: {} ".format(vim_tenant_dict
['vim_tenant_id'], str(e
))
3901 logger
.warn(warning
)
3902 except db_base_Exception
as e
:
3903 logger
.error("Cannot delete datacenter_tenants " + str(e
))
3904 pass # the error will be caused because dependencies, vim_tenant can not be deleted
3905 thread_id
= tenant_datacenter_item
["datacenter_tenant_id"]
3906 thread
= vim_threads
["running"][thread_id
]
3907 thread
.insert_task("exit")
3908 vim_threads
["deleting"][thread_id
] = thread
3909 return "datacenter {} detached. {}".format(datacenter_id
, warning
)
3912 def datacenter_action(mydb
, tenant_id
, datacenter
, action_dict
):
3914 #get datacenter info
3915 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3917 if 'net-update' in action_dict
:
3919 nets
= myvim
.get_network_list(filter_dict
={'shared': True, 'admin_state_up': True, 'status': 'ACTIVE'})
3921 except vimconn
.vimconnException
as e
:
3922 #logger.error("nfvo.datacenter_action() Not possible to get_network_list from VIM: %s ", str(e))
3923 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3924 #update nets Change from VIM format to NFVO format
3927 net_nfvo
={'datacenter_id': datacenter_id
}
3928 net_nfvo
['name'] = net
['name']
3929 #net_nfvo['description']= net['name']
3930 net_nfvo
['vim_net_id'] = net
['id']
3931 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3932 net_nfvo
['shared'] = net
['shared']
3933 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
3934 net_list
.append(net_nfvo
)
3935 inserted
, deleted
= mydb
.update_datacenter_nets(datacenter_id
, net_list
)
3936 logger
.info("Inserted %d nets, deleted %d old nets", inserted
, deleted
)
3938 elif 'net-edit' in action_dict
:
3939 net
= action_dict
['net-edit'].pop('net')
3940 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3941 result
= mydb
.update_rows('datacenter_nets', action_dict
['net-edit'],
3942 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3944 elif 'net-delete' in action_dict
:
3945 net
= action_dict
['net-deelte'].get('net')
3946 what
= 'vim_net_id' if utils
.check_valid_uuid(net
) else 'name'
3947 result
= mydb
.delete_row(FROM
='datacenter_nets',
3948 WHERE
={'datacenter_id':datacenter_id
, what
: net
})
3952 raise NfvoException("Unknown action " + str(action_dict
), HTTP_Bad_Request
)
3955 def datacenter_edit_netmap(mydb
, tenant_id
, datacenter
, netmap
, action_dict
):
3956 #get datacenter info
3957 datacenter_id
, _
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3959 what
= 'uuid' if utils
.check_valid_uuid(netmap
) else 'name'
3960 result
= mydb
.update_rows('datacenter_nets', action_dict
['netmap'],
3961 WHERE
={'datacenter_id':datacenter_id
, what
: netmap
})
3965 def datacenter_new_netmap(mydb
, tenant_id
, datacenter
, action_dict
=None):
3966 #get datacenter info
3967 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
3970 action_dict
= action_dict
["netmap"]
3971 if 'vim_id' in action_dict
:
3972 filter_dict
["id"] = action_dict
['vim_id']
3973 if 'vim_name' in action_dict
:
3974 filter_dict
["name"] = action_dict
['vim_name']
3976 filter_dict
["shared"] = True
3979 vim_nets
= myvim
.get_network_list(filter_dict
=filter_dict
)
3980 except vimconn
.vimconnException
as e
:
3981 #logger.error("nfvo.datacenter_new_netmap() Not possible to get_network_list from VIM: %s ", str(e))
3982 raise NfvoException(str(e
), HTTP_Internal_Server_Error
)
3983 if len(vim_nets
)>1 and action_dict
:
3984 raise NfvoException("more than two networks found, specify with vim_id", HTTP_Conflict
)
3985 elif len(vim_nets
)==0: # and action_dict:
3986 raise NfvoException("Not found a network at VIM with " + str(filter_dict
), HTTP_Not_Found
)
3988 for net
in vim_nets
:
3989 net_nfvo
={'datacenter_id': datacenter_id
}
3990 if action_dict
and "name" in action_dict
:
3991 net_nfvo
['name'] = action_dict
['name']
3993 net_nfvo
['name'] = net
['name']
3994 #net_nfvo['description']= net['name']
3995 net_nfvo
['vim_net_id'] = net
['id']
3996 net_nfvo
['type'] = net
['type'][0:6] #change from ('ptp','data','bridge_data','bridge_man') to ('bridge','data','ptp')
3997 net_nfvo
['shared'] = net
['shared']
3998 net_nfvo
['multipoint'] = False if net
['type']=='ptp' else True
4000 net_id
= mydb
.new_row("datacenter_nets", net_nfvo
, add_uuid
=True)
4001 net_nfvo
["status"] = "OK"
4002 net_nfvo
["uuid"] = net_id
4003 except db_base_Exception
as e
:
4007 net_nfvo
["status"] = "FAIL: " + str(e
)
4008 net_list
.append(net_nfvo
)
4011 def get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
):
4012 # obtain all network data
4014 if utils
.check_valid_uuid(network_id
):
4015 filter_dict
= {"id": network_id
}
4017 filter_dict
= {"name": network_id
}
4019 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4020 network
= myvim
.get_network_list(filter_dict
=filter_dict
)
4021 except vimconn
.vimconnException
as e
:
4022 raise NfvoException("Not possible to get_sdn_net_id from VIM: {}".format(str(e
)), e
.http_code
)
4024 # ensure the network is defined
4025 if len(network
) == 0:
4026 raise NfvoException("Network {} is not present in the system".format(network_id
),
4029 # ensure there is only one network with the provided name
4030 if len(network
) > 1:
4031 raise NfvoException("Multiple networks present in vim identified by {}".format(network_id
), HTTP_Bad_Request
)
4033 # ensure it is a dataplane network
4034 if network
[0]['type'] != 'data':
4037 # ensure we use the id
4038 network_id
= network
[0]['id']
4040 # search in dabase mano_db in table instance nets for the sdn_net_id that corresponds to the vim_net_id==network_id
4041 # and with instance_scenario_id==NULL
4042 #search_dict = {'vim_net_id': network_id, 'instance_scenario_id': None}
4043 search_dict
= {'vim_net_id': network_id
}
4046 #sdn_network_id = mydb.get_rows(SELECT=('sdn_net_id',), FROM='instance_nets', WHERE=search_dict)[0]['sdn_net_id']
4047 result
= mydb
.get_rows(SELECT
=('sdn_net_id',), FROM
='instance_nets', WHERE
=search_dict
)
4048 except db_base_Exception
as e
:
4049 raise NfvoException("db_base_Exception obtaining SDN network to associated to vim network {}".format(
4050 network_id
) + str(e
), HTTP_Internal_Server_Error
)
4054 if net
['sdn_net_id'] != None:
4056 sdn_net_id
= net
['sdn_net_id']
4058 if sdn_net_counter
== 0:
4060 elif sdn_net_counter
== 1:
4063 raise NfvoException("More than one SDN network is associated to vim network {}".format(
4064 network_id
), HTTP_Internal_Server_Error
)
4066 def get_sdn_controller_id(mydb
, datacenter
):
4067 # Obtain sdn controller id
4068 config
= mydb
.get_rows(SELECT
=('config',), FROM
='datacenters', WHERE
={'uuid': datacenter
})[0].get('config', '{}')
4072 return yaml
.load(config
).get('sdn-controller')
4074 def vim_net_sdn_attach(mydb
, tenant_id
, datacenter
, network_id
, descriptor
):
4076 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
4077 if not sdn_network_id
:
4078 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
), HTTP_Internal_Server_Error
)
4080 #Obtain sdn controller id
4081 controller_id
= get_sdn_controller_id(mydb
, datacenter
)
4082 if not controller_id
:
4083 raise NfvoException("No SDN controller is set for datacenter {}".format(datacenter
), HTTP_Internal_Server_Error
)
4085 #Obtain sdn controller info
4086 sdn_controller
= ovim
.show_of_controller(controller_id
)
4089 'name': 'external_port',
4090 'net_id': sdn_network_id
,
4091 'ofc_id': controller_id
,
4092 'switch_dpid': sdn_controller
['dpid'],
4093 'switch_port': descriptor
['port']
4096 if 'vlan' in descriptor
:
4097 port_data
['vlan'] = descriptor
['vlan']
4098 if 'mac' in descriptor
:
4099 port_data
['mac'] = descriptor
['mac']
4101 result
= ovim
.new_port(port_data
)
4102 except ovimException
as e
:
4103 raise NfvoException("ovimException attaching SDN network {} to vim network {}".format(
4104 sdn_network_id
, network_id
) + str(e
), HTTP_Internal_Server_Error
)
4105 except db_base_Exception
as e
:
4106 raise NfvoException("db_base_Exception attaching SDN network to vim network {}".format(
4107 network_id
) + str(e
), HTTP_Internal_Server_Error
)
4109 return 'Port uuid: '+ result
4111 def vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, network_id
, port_id
=None):
4113 filter = {'uuid': port_id
}
4115 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, network_id
)
4116 if not sdn_network_id
:
4117 raise NfvoException("No SDN network is associated to vim-network {}".format(network_id
),
4118 HTTP_Internal_Server_Error
)
4119 #in case no port_id is specified only ports marked as 'external_port' will be detached
4120 filter = {'name': 'external_port', 'net_id': sdn_network_id
}
4123 port_list
= ovim
.get_ports(columns
={'uuid'}, filter=filter)
4124 except ovimException
as e
:
4125 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
4126 HTTP_Internal_Server_Error
)
4128 if len(port_list
) == 0:
4129 raise NfvoException("No ports attached to the network {} were found with the requested criteria".format(network_id
),
4133 for port
in port_list
:
4135 port_uuid_list
.append(port
['uuid'])
4136 ovim
.delete_port(port
['uuid'])
4137 except ovimException
as e
:
4138 raise NfvoException("ovimException deleting port {} for net {}. ".format(port
['uuid'], network_id
) + str(e
), HTTP_Internal_Server_Error
)
4140 return 'Detached ports uuid: {}'.format(','.join(port_uuid_list
))
4142 def vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
):
4143 #get datacenter info
4144 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4147 if utils
.check_valid_uuid(name
):
4148 filter_dict
["id"] = name
4150 filter_dict
["name"] = name
4152 if item
=="networks":
4153 #filter_dict['tenant_id'] = myvim['tenant_id']
4154 content
= myvim
.get_network_list(filter_dict
=filter_dict
)
4156 if len(content
) == 0:
4157 raise NfvoException("Network {} is not present in the system. ".format(name
),
4160 #Update the networks with the attached ports
4162 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, net
['id'])
4163 if sdn_network_id
!= None:
4165 #port_list = ovim.get_ports(columns={'uuid', 'switch_port', 'vlan'}, filter={'name': 'external_port', 'net_id': sdn_network_id})
4166 port_list
= ovim
.get_ports(columns
={'uuid', 'switch_port', 'vlan','name'}, filter={'net_id': sdn_network_id
})
4167 except ovimException
as e
:
4168 raise NfvoException("ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
), HTTP_Internal_Server_Error
)
4169 #Remove field name and if port name is external_port save it as 'type'
4170 for port
in port_list
:
4171 if port
['name'] == 'external_port':
4172 port
['type'] = "External"
4174 net
['sdn_network_id'] = sdn_network_id
4175 net
['sdn_attached_ports'] = port_list
4177 elif item
=="tenants":
4178 content
= myvim
.get_tenant_list(filter_dict
=filter_dict
)
4179 elif item
== "images":
4181 content
= myvim
.get_image_list(filter_dict
=filter_dict
)
4183 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4184 logger
.debug("vim_action response %s", content
) #update nets Change from VIM format to NFVO format
4185 if name
and len(content
)==1:
4186 return {item
[:-1]: content
[0]}
4187 elif name
and len(content
)==0:
4188 raise NfvoException("No {} found with ".format(item
[:-1]) + " and ".join(map(lambda x
: str(x
[0])+": "+str(x
[1]), filter_dict
.iteritems())),
4191 return {item
: content
}
4192 except vimconn
.vimconnException
as e
:
4193 print "vim_action Not possible to get_%s_list from VIM: %s " % (item
, str(e
))
4194 raise NfvoException("Not possible to get_{}_list from VIM: {}".format(item
, str(e
)), e
.http_code
)
4197 def vim_action_delete(mydb
, tenant_id
, datacenter
, item
, name
):
4198 #get datacenter info
4199 if tenant_id
== "any":
4202 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4204 content
= vim_action_get(mydb
, tenant_id
, datacenter
, item
, name
)
4205 logger
.debug("vim_action_delete vim response: " + str(content
))
4206 items
= content
.values()[0]
4207 if type(items
)==list and len(items
)==0:
4208 raise NfvoException("Not found " + item
, HTTP_Not_Found
)
4209 elif type(items
)==list and len(items
)>1:
4210 raise NfvoException("Found more than one {} with this name. Use uuid.".format(item
), HTTP_Not_Found
)
4211 else: # it is a dict
4212 item_id
= items
["id"]
4213 item_name
= str(items
.get("name"))
4216 if item
=="networks":
4217 # If there is a SDN network associated to the vim-network, proceed to clear the relationship and delete it
4218 sdn_network_id
= get_sdn_net_id(mydb
, tenant_id
, datacenter
, item_id
)
4219 if sdn_network_id
!= None:
4220 #Delete any port attachment to this network
4222 port_list
= ovim
.get_ports(columns
={'uuid'}, filter={'net_id': sdn_network_id
})
4223 except ovimException
as e
:
4224 raise NfvoException(
4225 "ovimException obtaining external ports for net {}. ".format(network_id
) + str(e
),
4226 HTTP_Internal_Server_Error
)
4228 # By calling one by one all ports to be detached we ensure that not only the external_ports get detached
4229 for port
in port_list
:
4230 vim_net_sdn_detach(mydb
, tenant_id
, datacenter
, item_id
, port
['uuid'])
4232 #Delete from 'instance_nets' the correspondence between the vim-net-id and the sdn-net-id
4234 mydb
.delete_row(FROM
='instance_nets', WHERE
={'instance_scenario_id': None, 'sdn_net_id': sdn_network_id
, 'vim_net_id': item_id
})
4235 except db_base_Exception
as e
:
4236 raise NfvoException("Error deleting correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
4237 str(e
), HTTP_Internal_Server_Error
)
4239 #Delete the SDN network
4241 ovim
.delete_network(sdn_network_id
)
4242 except ovimException
as e
:
4243 logger
.error("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
), exc_info
=True)
4244 raise NfvoException("ovimException deleting SDN network={} ".format(sdn_network_id
) + str(e
),
4245 HTTP_Internal_Server_Error
)
4247 content
= myvim
.delete_network(item_id
)
4248 elif item
=="tenants":
4249 content
= myvim
.delete_tenant(item_id
)
4250 elif item
== "images":
4251 content
= myvim
.delete_image(item_id
)
4253 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4254 except vimconn
.vimconnException
as e
:
4255 #logger.error( "vim_action Not possible to delete_{} {}from VIM: {} ".format(item, name, str(e)))
4256 raise NfvoException("Not possible to delete_{} {} from VIM: {}".format(item
, name
, str(e
)), e
.http_code
)
4258 return "{} {} {} deleted".format(item
[:-1], item_id
,item_name
)
4261 def vim_action_create(mydb
, tenant_id
, datacenter
, item
, descriptor
):
4262 #get datacenter info
4263 logger
.debug("vim_action_create descriptor %s", str(descriptor
))
4264 if tenant_id
== "any":
4266 datacenter_id
, myvim
= get_datacenter_by_name_uuid(mydb
, tenant_id
, datacenter
)
4268 if item
=="networks":
4269 net
= descriptor
["network"]
4270 net_name
= net
.pop("name")
4271 net_type
= net
.pop("type", "bridge")
4272 net_public
= net
.pop("shared", False)
4273 net_ipprofile
= net
.pop("ip_profile", None)
4274 net_vlan
= net
.pop("vlan", None)
4275 content
= myvim
.new_network(net_name
, net_type
, net_ipprofile
, shared
=net_public
, vlan
=net_vlan
) #, **net)
4277 #If the datacenter has a SDN controller defined and the network is of dataplane type, then create the sdn network
4278 if get_sdn_controller_id(mydb
, datacenter
) != None and (net_type
== 'data' or net_type
== 'ptp'):
4281 sdn_network
['vlan'] = net_vlan
4282 sdn_network
['type'] = net_type
4283 sdn_network
['name'] = net_name
4284 ovim_content
= ovim
.new_network(sdn_network
)
4285 except ovimException
as e
:
4286 self
.logger
.error("ovimException creating SDN network={} ".format(
4287 sdn_network
) + str(e
), exc_info
=True)
4288 raise NfvoException("ovimException creating SDN network={} ".format(sdn_network
) + str(e
),
4289 HTTP_Internal_Server_Error
)
4291 # Save entry in in dabase mano_db in table instance_nets to stablish a dictionary vim_net_id <->sdn_net_id
4292 # use instance_scenario_id=None to distinguish from real instaces of nets
4293 correspondence
= {'instance_scenario_id': None, 'sdn_net_id': ovim_content
, 'vim_net_id': content
}
4294 #obtain datacenter_tenant_id
4295 correspondence
['datacenter_tenant_id'] = mydb
.get_rows(SELECT
=('uuid',), FROM
='datacenter_tenants', WHERE
={'datacenter_id': datacenter
})[0]['uuid']
4298 mydb
.new_row('instance_nets', correspondence
, add_uuid
=True)
4299 except db_base_Exception
as e
:
4300 raise NfvoException("Error saving correspondence for VIM/SDN dataplane networks{}: ".format(correspondence
) +
4301 str(e
), HTTP_Internal_Server_Error
)
4302 elif item
=="tenants":
4303 tenant
= descriptor
["tenant"]
4304 content
= myvim
.new_tenant(tenant
["name"], tenant
.get("description"))
4306 raise NfvoException(item
+ "?", HTTP_Method_Not_Allowed
)
4307 except vimconn
.vimconnException
as e
:
4308 raise NfvoException("Not possible to create {} at VIM: {}".format(item
, str(e
)), e
.http_code
)
4310 return vim_action_get(mydb
, tenant_id
, datacenter
, item
, content
)
4312 def sdn_controller_create(mydb
, tenant_id
, sdn_controller
):
4313 data
= ovim
.new_of_controller(sdn_controller
)
4314 logger
.debug('New SDN controller created with uuid {}'.format(data
))
4317 def sdn_controller_update(mydb
, tenant_id
, controller_id
, sdn_controller
):
4318 data
= ovim
.edit_of_controller(controller_id
, sdn_controller
)
4319 msg
= 'SDN controller {} updated'.format(data
)
4323 def sdn_controller_list(mydb
, tenant_id
, controller_id
=None):
4324 if controller_id
== None:
4325 data
= ovim
.get_of_controllers()
4327 data
= ovim
.show_of_controller(controller_id
)
4329 msg
= 'SDN controller list:\n {}'.format(data
)
4333 def sdn_controller_delete(mydb
, tenant_id
, controller_id
):
4334 select_
= ('uuid', 'config')
4335 datacenters
= mydb
.get_rows(FROM
='datacenters', SELECT
=select_
)
4336 for datacenter
in datacenters
:
4337 if datacenter
['config']:
4338 config
= yaml
.load(datacenter
['config'])
4339 if 'sdn-controller' in config
and config
['sdn-controller'] == controller_id
:
4340 raise NfvoException("SDN controller {} is in use by datacenter {}".format(controller_id
, datacenter
['uuid']), HTTP_Conflict
)
4342 data
= ovim
.delete_of_controller(controller_id
)
4343 msg
= 'SDN controller {} deleted'.format(data
)
4347 def datacenter_sdn_port_mapping_set(mydb
, tenant_id
, datacenter_id
, sdn_port_mapping
):
4348 controller
= mydb
.get_rows(FROM
="datacenters", SELECT
=("config",), WHERE
={"uuid":datacenter_id
})
4349 if len(controller
) < 1:
4350 raise NfvoException("Datacenter {} not present in the database".format(datacenter_id
), HTTP_Not_Found
)
4353 sdn_controller_id
= yaml
.load(controller
[0]["config"])["sdn-controller"]
4355 raise NfvoException("The datacenter {} has not an SDN controller associated".format(datacenter_id
), HTTP_Bad_Request
)
4357 sdn_controller
= ovim
.show_of_controller(sdn_controller_id
)
4358 switch_dpid
= sdn_controller
["dpid"]
4361 for compute_node
in sdn_port_mapping
:
4362 #element = {"ofc_id": sdn_controller_id, "region": datacenter_id, "switch_dpid": switch_dpid}
4364 element
["compute_node"] = compute_node
["compute_node"]
4365 for port
in compute_node
["ports"]:
4366 element
["pci"] = port
.get("pci")
4367 element
["switch_port"] = port
.get("switch_port")
4368 element
["switch_mac"] = port
.get("switch_mac")
4369 if not element
["pci"] or not (element
["switch_port"] or element
["switch_mac"]):
4370 raise NfvoException ("The mapping must contain the 'pci' and at least one of the elements 'switch_port'"
4371 " or 'switch_mac'", HTTP_Bad_Request
)
4372 maps
.append(dict(element
))
4374 return ovim
.set_of_port_mapping(maps
, ofc_id
=sdn_controller_id
, switch_dpid
=switch_dpid
, region
=datacenter_id
)
4376 def datacenter_sdn_port_mapping_list(mydb
, tenant_id
, datacenter_id
):
4377 maps
= ovim
.get_of_port_mappings(db_filter
={"region": datacenter_id
})
4380 "sdn-controller": None,
4381 "datacenter-id": datacenter_id
,
4383 "ports_mapping": list()
4386 datacenter
= mydb
.get_table_by_uuid_name('datacenters', datacenter_id
)
4387 if datacenter
['config']:
4388 config
= yaml
.load(datacenter
['config'])
4389 if 'sdn-controller' in config
:
4390 controller_id
= config
['sdn-controller']
4391 sdn_controller
= sdn_controller_list(mydb
, tenant_id
, controller_id
)
4392 result
["sdn-controller"] = controller_id
4393 result
["dpid"] = sdn_controller
["dpid"]
4395 if result
["sdn-controller"] == None:
4396 raise NfvoException("SDN controller is not defined for datacenter {}".format(datacenter_id
), HTTP_Bad_Request
)
4397 if result
["dpid"] == None:
4398 raise NfvoException("It was not possible to determine DPID for SDN controller {}".format(result
["sdn-controller"]),
4399 HTTP_Internal_Server_Error
)
4404 ports_correspondence_dict
= dict()
4406 if result
["sdn-controller"] != link
["ofc_id"]:
4407 raise NfvoException("The sdn-controller specified for different port mappings differ", HTTP_Internal_Server_Error
)
4408 if result
["dpid"] != link
["switch_dpid"]:
4409 raise NfvoException("The dpid specified for different port mappings differ", HTTP_Internal_Server_Error
)
4411 element
["pci"] = link
["pci"]
4412 if link
["switch_port"]:
4413 element
["switch_port"] = link
["switch_port"]
4414 if link
["switch_mac"]:
4415 element
["switch_mac"] = link
["switch_mac"]
4417 if not link
["compute_node"] in ports_correspondence_dict
:
4419 content
["compute_node"] = link
["compute_node"]
4420 content
["ports"] = list()
4421 ports_correspondence_dict
[link
["compute_node"]] = content
4423 ports_correspondence_dict
[link
["compute_node"]]["ports"].append(element
)
4425 for key
in sorted(ports_correspondence_dict
):
4426 result
["ports_mapping"].append(ports_correspondence_dict
[key
])
4430 def datacenter_sdn_port_mapping_delete(mydb
, tenant_id
, datacenter_id
):
4431 return ovim
.clear_of_port_mapping(db_filter
={"region":datacenter_id
})
4433 def create_RO_keypair(tenant_id
):
4435 Creates a public / private keys for a RO tenant and returns their values
4437 tenant_id: ID of the tenant
4439 public_key: Public key for the RO tenant
4440 private_key: Encrypted private key for RO tenant
4444 key
= RSA
.generate(bits
)
4446 public_key
= key
.publickey().exportKey('OpenSSH')
4447 if isinstance(public_key
, ValueError):
4448 raise NfvoException("Unable to create public key: {}".format(public_key
), HTTP_Internal_Server_Error
)
4449 private_key
= key
.exportKey(passphrase
=tenant_id
, pkcs
=8)
4450 except (ValueError, NameError) as e
:
4451 raise NfvoException("Unable to create private key: {}".format(e
), HTTP_Internal_Server_Error
)
4452 return public_key
, private_key
4454 def decrypt_key (key
, tenant_id
):
4456 Decrypts an encrypted RSA key
4458 key: Private key to be decrypted
4459 tenant_id: ID of the tenant
4461 unencrypted_key: Unencrypted private key for RO tenant
4464 key
= RSA
.importKey(key
,tenant_id
)
4465 unencrypted_key
= key
.exportKey('PEM')
4466 if isinstance(unencrypted_key
, ValueError):
4467 raise NfvoException("Unable to decrypt the private key: {}".format(unencrypted_key
), HTTP_Internal_Server_Error
)
4468 except ValueError as e
:
4469 raise NfvoException("Unable to decrypt the private key: {}".format(e
), HTTP_Internal_Server_Error
)
4470 return unencrypted_key