blob: 11aee15798fa6b5ee07a4754324fd4b1c61bfc31 [file] [log] [blame]
tierno7edb6752016-03-21 17:37:52 +01001# -*- coding: utf-8 -*-
2
3##
4# Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
5# This file is part of openmano
6# All Rights Reserved.
7#
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
11#
12# http://www.apache.org/licenses/LICENSE-2.0
13#
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
18# under the License.
19#
20# For those usages not covered by the Apache License, Version 2.0 please
21# contact with: nfvlabs@tid.es
22##
23
24'''
25HTTP server implementing the openmano API. It will answer to POST, PUT, GET methods in the appropriate URLs
26and will use the nfvo.py module to run the appropriate method.
Anderson Bravalheri0446cd52018-08-17 15:26:19 +010027Every YAML/JSON file is checked against a schema in openmano_schemas.py module.
tierno7edb6752016-03-21 17:37:52 +010028'''
29__author__="Alfonso Tierno, Gerardo Garcia"
30__date__ ="$17-sep-2014 09:07:15$"
31
32import bottle
33import yaml
tierno7edb6752016-03-21 17:37:52 +010034import threading
tiernof97fd272016-07-11 14:32:37 +020035import logging
tierno7edb6752016-03-21 17:37:52 +010036
tierno7edb6752016-03-21 17:37:52 +010037from openmano_schemas import vnfd_schema_v01, vnfd_schema_v02, \
garciadeblas9f8456e2016-09-05 05:02:59 +020038 nsd_schema_v01, nsd_schema_v02, nsd_schema_v03, scenario_edit_schema, \
garciadeblas0c317ee2016-08-29 12:33:06 +020039 scenario_action_schema, instance_scenario_action_schema, instance_scenario_create_schema_v01, \
tierno7edb6752016-03-21 17:37:52 +010040 tenant_schema, tenant_edit_schema,\
41 datacenter_schema, datacenter_edit_schema, datacenter_action_schema, datacenter_associate_schema,\
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +010042 object_schema, netmap_new_schema, netmap_edit_schema, sdn_controller_schema, sdn_controller_edit_schema, \
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +020043 sdn_port_mapping_schema, sdn_external_port_schema
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +010044
Anderson Bravalheri0446cd52018-08-17 15:26:19 +010045from .http_tools import errors as httperrors
46from .http_tools.request_processing import (
47 format_out,
48 format_in,
49 filter_query_string
50)
51from .wim.http_handler import WimHandler
52
tierno7edb6752016-03-21 17:37:52 +010053import nfvo
tierno42fcc3b2016-07-06 17:20:40 +020054import utils
tiernof97fd272016-07-11 14:32:37 +020055from db_base import db_base_Exception
56from functools import wraps
tierno7edb6752016-03-21 17:37:52 +010057
58global mydb
59global url_base
tiernof97fd272016-07-11 14:32:37 +020060global logger
tierno7edb6752016-03-21 17:37:52 +010061url_base="/openmano"
tierno73ad9e42016-09-12 18:11:11 +020062logger = None
tierno7edb6752016-03-21 17:37:52 +010063
tierno7edb6752016-03-21 17:37:52 +010064
tiernof97fd272016-07-11 14:32:37 +020065def log_to_logger(fn):
66 '''
67 Wrap a Bottle request so that a log line is emitted after it's handled.
68 (This decorator can be extended to take the desired logger as a param.)
69 '''
70 @wraps(fn)
71 def _log_to_logger(*args, **kwargs):
72 actual_response = fn(*args, **kwargs)
73 # modify this to log exactly what you need:
Anderson Bravalheri0446cd52018-08-17 15:26:19 +010074 logger.info('FROM %s %s %s %s', bottle.request.remote_addr,
tiernof97fd272016-07-11 14:32:37 +020075 bottle.request.method,
76 bottle.request.url,
Anderson Bravalheri0446cd52018-08-17 15:26:19 +010077 bottle.response.status)
tiernof97fd272016-07-11 14:32:37 +020078 return actual_response
79 return _log_to_logger
tierno7edb6752016-03-21 17:37:52 +010080
81class httpserver(threading.Thread):
Anderson Bravalheri0446cd52018-08-17 15:26:19 +010082 def __init__(self, db, admin=False, host='localhost', port=9090,
83 wim_persistence=None, wim_engine=None):
tierno7edb6752016-03-21 17:37:52 +010084 #global url_base
85 global mydb
tiernof97fd272016-07-11 14:32:37 +020086 global logger
tierno7edb6752016-03-21 17:37:52 +010087 #initialization
tierno73ad9e42016-09-12 18:11:11 +020088 if not logger:
89 logger = logging.getLogger('openmano.http')
tierno7edb6752016-03-21 17:37:52 +010090 threading.Thread.__init__(self)
91 self.host = host
92 self.port = port #Port where the listen service must be started
93 if admin==True:
94 self.name = "http_admin"
95 else:
96 self.name = "http"
97 #self.url_preffix = 'http://' + host + ':' + str(port) + url_base
98 mydb = db
99 #self.first_usable_connection_index = 10
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100100 #self.next_connection_index = self.first_usable_connection_index #The next connection index to be used
tierno7edb6752016-03-21 17:37:52 +0100101 #Ensure that when the main program exits the thread will also exit
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100102
103 self.handlers = [
104 WimHandler(db, wim_persistence, wim_engine, url_base)
105 ]
106
tierno7edb6752016-03-21 17:37:52 +0100107 self.daemon = True
108 self.setDaemon(True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100109
110 def run(self, debug=False, quiet=True):
tiernof97fd272016-07-11 14:32:37 +0200111 bottle.install(log_to_logger)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100112 default_app = bottle.app()
113
114 for handler in self.handlers:
115 default_app.merge(handler.wsgi_app)
116
117 bottle.run(host=self.host, port=self.port, debug=debug, quiet=quiet)
118
119
tierno7edb6752016-03-21 17:37:52 +0100120def run_bottle(db, host_='localhost', port_=9090):
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100121 '''Used for launching in main thread, so that it can be debugged'''
122 server = httpserver(db, host=host_, port=port_)
123 server.run(debug=True) # quiet=True
124
tierno7edb6752016-03-21 17:37:52 +0100125
126@bottle.route(url_base + '/', method='GET')
127def http_get():
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100128 #print
tierno7edb6752016-03-21 17:37:52 +0100129 return 'works' #TODO: to be completed
130
tierno7edb6752016-03-21 17:37:52 +0100131@bottle.hook('after_request')
132def enable_cors():
133 '''Don't know yet if really needed. Keep it just in case'''
134 bottle.response.headers['Access-Control-Allow-Origin'] = '*'
135
tierno6ddeded2017-05-16 15:40:26 +0200136@bottle.route(url_base + '/version', method='GET')
137def http_get_version():
138 return nfvo.get_version()
tierno7edb6752016-03-21 17:37:52 +0100139#
140# VNFs
141#
142
143@bottle.route(url_base + '/tenants', method='GET')
144def http_get_tenants():
tiernof97fd272016-07-11 14:32:37 +0200145 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno7edb6752016-03-21 17:37:52 +0100146 select_,where_,limit_ = filter_query_string(bottle.request.query, None,
147 ('uuid','name','description','created_at') )
tiernof97fd272016-07-11 14:32:37 +0200148 try:
149 tenants = mydb.get_rows(FROM='nfvo_tenants', SELECT=select_,WHERE=where_,LIMIT=limit_)
tierno7edb6752016-03-21 17:37:52 +0100150 #change_keys_http2db(content, http2db_tenant, reverse=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100151 utils.convert_float_timestamp2str(tenants)
tiernof97fd272016-07-11 14:32:37 +0200152 data={'tenants' : tenants}
tierno7edb6752016-03-21 17:37:52 +0100153 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +0200154 except bottle.HTTPError:
155 raise
tiernof97fd272016-07-11 14:32:37 +0200156 except db_base_Exception as e:
157 logger.error("http_get_tenants error {}: {}".format(e.http_code, str(e)))
158 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000159 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000160 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100161 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000162
tierno7edb6752016-03-21 17:37:52 +0100163
164@bottle.route(url_base + '/tenants/<tenant_id>', method='GET')
165def http_get_tenant_id(tenant_id):
166 '''get tenant details, can use both uuid or name'''
167 #obtain data
tiernof97fd272016-07-11 14:32:37 +0200168 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
169 try:
gcalvinoc62cfa52017-10-05 18:21:25 +0200170 from_ = 'nfvo_tenants'
171 select_, where_, limit_ = filter_query_string(bottle.request.query, None,
172 ('uuid', 'name', 'description', 'created_at'))
tiernod2b560b2017-10-11 10:30:18 +0200173 what = 'uuid' if utils.check_valid_uuid(tenant_id) else 'name'
174 where_[what] = tenant_id
tierno9c22f2d2017-10-09 16:23:55 +0200175 tenants = mydb.get_rows(FROM=from_, SELECT=select_,WHERE=where_)
tiernof97fd272016-07-11 14:32:37 +0200176 #change_keys_http2db(content, http2db_tenant, reverse=True)
tiernod2b560b2017-10-11 10:30:18 +0200177 if len(tenants) == 0:
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100178 bottle.abort(httperrors.Not_Found, "No tenant found with {}='{}'".format(what, tenant_id))
tiernod2b560b2017-10-11 10:30:18 +0200179 elif len(tenants) > 1:
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100180 bottle.abort(httperrors.Bad_Request, "More than one tenant found with {}='{}'".format(what, tenant_id))
181 utils.convert_float_timestamp2str(tenants[0])
tiernod2b560b2017-10-11 10:30:18 +0200182 data = {'tenant': tenants[0]}
tiernof97fd272016-07-11 14:32:37 +0200183 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +0200184 except bottle.HTTPError:
185 raise
tiernof97fd272016-07-11 14:32:37 +0200186 except db_base_Exception as e:
187 logger.error("http_get_tenant_id error {}: {}".format(e.http_code, str(e)))
188 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000189 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000190 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100191 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000192
tierno7edb6752016-03-21 17:37:52 +0100193
194@bottle.route(url_base + '/tenants', method='POST')
195def http_post_tenants():
196 '''insert a tenant into the catalogue. '''
197 #parse input data
tiernof97fd272016-07-11 14:32:37 +0200198 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno7edb6752016-03-21 17:37:52 +0100199 http_content,_ = format_in( tenant_schema )
tierno42fcc3b2016-07-06 17:20:40 +0200200 r = utils.remove_extra_items(http_content, tenant_schema)
tiernoefd80c92016-09-16 14:17:46 +0200201 if r:
202 logger.debug("Remove received extra items %s", str(r))
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100203 try:
tiernof97fd272016-07-11 14:32:37 +0200204 data = nfvo.new_tenant(mydb, http_content['tenant'])
tierno7edb6752016-03-21 17:37:52 +0100205 return http_get_tenant_id(data)
tiernod2b560b2017-10-11 10:30:18 +0200206 except bottle.HTTPError:
207 raise
tiernof97fd272016-07-11 14:32:37 +0200208 except (nfvo.NfvoException, db_base_Exception) as e:
209 logger.error("http_post_tenants error {}: {}".format(e.http_code, str(e)))
210 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000211 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000212 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100213 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000214
tierno7edb6752016-03-21 17:37:52 +0100215
216@bottle.route(url_base + '/tenants/<tenant_id>', method='PUT')
217def http_edit_tenant_id(tenant_id):
218 '''edit tenant details, can use both uuid or name'''
219 #parse input data
tiernof97fd272016-07-11 14:32:37 +0200220 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno7edb6752016-03-21 17:37:52 +0100221 http_content,_ = format_in( tenant_edit_schema )
tierno42fcc3b2016-07-06 17:20:40 +0200222 r = utils.remove_extra_items(http_content, tenant_edit_schema)
tiernoefd80c92016-09-16 14:17:46 +0200223 if r:
224 logger.debug("Remove received extra items %s", str(r))
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100225
tierno7edb6752016-03-21 17:37:52 +0100226 #obtain data, check that only one exist
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100227 try:
tiernof97fd272016-07-11 14:32:37 +0200228 tenant = mydb.get_table_by_uuid_name('nfvo_tenants', tenant_id)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100229 #edit data
tiernof97fd272016-07-11 14:32:37 +0200230 tenant_id = tenant['uuid']
231 where={'uuid': tenant['uuid']}
232 mydb.update_rows('nfvo_tenants', http_content['tenant'], where)
233 return http_get_tenant_id(tenant_id)
tiernod2b560b2017-10-11 10:30:18 +0200234 except bottle.HTTPError:
235 raise
tiernof97fd272016-07-11 14:32:37 +0200236 except db_base_Exception as e:
237 logger.error("http_edit_tenant_id error {}: {}".format(e.http_code, str(e)))
238 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000239 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000240 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100241 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000242
tierno7edb6752016-03-21 17:37:52 +0100243
244@bottle.route(url_base + '/tenants/<tenant_id>', method='DELETE')
245def http_delete_tenant_id(tenant_id):
246 '''delete a tenant from database, can use both uuid or name'''
tiernof97fd272016-07-11 14:32:37 +0200247 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
248 try:
249 data = nfvo.delete_tenant(mydb, tenant_id)
tierno7edb6752016-03-21 17:37:52 +0100250 return format_out({"result":"tenant " + data + " deleted"})
tiernod2b560b2017-10-11 10:30:18 +0200251 except bottle.HTTPError:
252 raise
tiernof97fd272016-07-11 14:32:37 +0200253 except db_base_Exception as e:
254 logger.error("http_delete_tenant_id error {}: {}".format(e.http_code, str(e)))
255 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000256 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000257 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100258 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000259
tierno7edb6752016-03-21 17:37:52 +0100260
261@bottle.route(url_base + '/<tenant_id>/datacenters', method='GET')
262def http_get_datacenters(tenant_id):
tiernof97fd272016-07-11 14:32:37 +0200263 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
264 try:
265 if tenant_id != 'any':
266 #check valid tenant_id
267 nfvo.check_tenant(mydb, tenant_id)
268 select_,where_,limit_ = filter_query_string(bottle.request.query, None,
269 ('uuid','name','vim_url','type','created_at') )
270 if tenant_id != 'any':
271 where_['nfvo_tenant_id'] = tenant_id
272 if 'created_at' in select_:
273 select_[ select_.index('created_at') ] = 'd.created_at as created_at'
274 if 'created_at' in where_:
275 where_['d.created_at'] = where_.pop('created_at')
276 datacenters = mydb.get_rows(FROM='datacenters as d join tenants_datacenters as td on d.uuid=td.datacenter_id',
277 SELECT=select_,WHERE=where_,LIMIT=limit_)
278 else:
279 datacenters = mydb.get_rows(FROM='datacenters',
280 SELECT=select_,WHERE=where_,LIMIT=limit_)
tierno7edb6752016-03-21 17:37:52 +0100281 #change_keys_http2db(content, http2db_tenant, reverse=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100282 utils.convert_float_timestamp2str(datacenters)
tiernof97fd272016-07-11 14:32:37 +0200283 data={'datacenters' : datacenters}
tierno7edb6752016-03-21 17:37:52 +0100284 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +0200285 except bottle.HTTPError:
286 raise
tiernof97fd272016-07-11 14:32:37 +0200287 except (nfvo.NfvoException, db_base_Exception) as e:
288 logger.error("http_get_datacenters error {}: {}".format(e.http_code, str(e)))
289 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000290 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000291 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100292 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000293
tierno7edb6752016-03-21 17:37:52 +0100294
tiernod3750b32018-07-20 15:33:08 +0200295@bottle.route(url_base + '/<tenant_id>/vim_accounts', method='GET')
296@bottle.route(url_base + '/<tenant_id>/vim_accounts/<vim_account_id>', method='GET')
297def http_get_vim_account(tenant_id, vim_account_id=None):
298 '''get vim_account list/details, '''
299 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
300 try:
301 select_ = ('uuid', 'name', 'dt.datacenter_id as vim_id', 'vim_tenant_name', 'vim_tenant_id', 'user', 'config',
302 'dt.created_at as created_at', 'passwd')
303 where_ = {'nfvo_tenant_id': tenant_id}
304 if vim_account_id:
305 where_['dt.uuid'] = vim_account_id
306 from_ = 'tenants_datacenters as td join datacenter_tenants as dt on dt.uuid=td.datacenter_tenant_id'
307 vim_accounts = mydb.get_rows(SELECT=select_, FROM=from_, WHERE=where_)
308
309 if len(vim_accounts) == 0 and vim_account_id:
310 bottle.abort(HTTP_Not_Found, "No vim_account found for tenant {} and id '{}'".format(tenant_id,
311 vim_account_id))
312 for vim_account in vim_accounts:
313 if vim_account["passwd"]:
314 vim_account["passwd"] = "******"
315 if vim_account['config'] != None:
316 try:
317 config_dict = yaml.load(vim_account['config'])
318 vim_account['config'] = config_dict
319 if vim_account['config'].get('admin_password'):
320 vim_account['config']['admin_password'] = "******"
321 if vim_account['config'].get('vcenter_password'):
322 vim_account['config']['vcenter_password'] = "******"
323 if vim_account['config'].get('nsx_password'):
324 vim_account['config']['nsx_password'] = "******"
325 except Exception as e:
326 logger.error("Exception '%s' while trying to load config information", str(e))
327 # change_keys_http2db(content, http2db_datacenter, reverse=True)
328 #convert_datetime2str(vim_account)
329 if vim_account_id:
330 return format_out({"datacenter": vim_accounts[0]})
331 else:
332 return format_out({"datacenters": vim_accounts})
333 except bottle.HTTPError:
334 raise
335 except (nfvo.NfvoException, db_base_Exception) as e:
336 logger.error("http_get_datacenter_id error {}: {}".format(e.http_code, str(e)))
337 bottle.abort(e.http_code, str(e))
338 except Exception as e:
339 logger.error("Unexpected exception: ", exc_info=True)
340 bottle.abort(HTTP_Internal_Server_Error, type(e).__name__ + ": " + str(e))
341
342
tierno7edb6752016-03-21 17:37:52 +0100343@bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>', method='GET')
344def http_get_datacenter_id(tenant_id, datacenter_id):
345 '''get datacenter details, can use both uuid or name'''
tiernof97fd272016-07-11 14:32:37 +0200346 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
347 try:
348 if tenant_id != 'any':
349 #check valid tenant_id
350 nfvo.check_tenant(mydb, tenant_id)
351 #obtain data
352 what = 'uuid' if utils.check_valid_uuid(datacenter_id) else 'name'
353 where_={}
354 where_[what] = datacenter_id
tierno8008c3a2016-10-13 15:34:28 +0000355 select_=['uuid', 'name','vim_url', 'vim_url_admin', 'type', 'd.config as config', 'description', 'd.created_at as created_at']
tiernof97fd272016-07-11 14:32:37 +0200356 if tenant_id != 'any':
357 select_.append("datacenter_tenant_id")
358 where_['td.nfvo_tenant_id']= tenant_id
359 from_='datacenters as d join tenants_datacenters as td on d.uuid=td.datacenter_id'
360 else:
361 from_='datacenters as d'
362 datacenters = mydb.get_rows(
363 SELECT=select_,
364 FROM=from_,
365 WHERE=where_)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100366
tiernof97fd272016-07-11 14:32:37 +0200367 if len(datacenters)==0:
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100368 bottle.abort( httperrors.Not_Found, "No datacenter found for tenant with {} '{}'".format(what, datacenter_id) )
369 elif len(datacenters)>1:
370 bottle.abort( httperrors.Bad_Request, "More than one datacenter found for tenant with {} '{}'".format(what, datacenter_id) )
tiernof97fd272016-07-11 14:32:37 +0200371 datacenter = datacenters[0]
372 if tenant_id != 'any':
373 #get vim tenant info
374 vim_tenants = mydb.get_rows(
tierno8008c3a2016-10-13 15:34:28 +0000375 SELECT=("vim_tenant_name", "vim_tenant_id", "user", "passwd", "config"),
tiernof97fd272016-07-11 14:32:37 +0200376 FROM="datacenter_tenants",
377 WHERE={"uuid": datacenters[0]["datacenter_tenant_id"]},
378 ORDER_BY=("created", ) )
379 del datacenter["datacenter_tenant_id"]
380 datacenter["vim_tenants"] = vim_tenants
tierno8008c3a2016-10-13 15:34:28 +0000381 for vim_tenant in vim_tenants:
382 if vim_tenant["passwd"]:
383 vim_tenant["passwd"] = "******"
384 if vim_tenant['config'] != None:
385 try:
386 config_dict = yaml.load(vim_tenant['config'])
387 vim_tenant['config'] = config_dict
gcalvinoc62cfa52017-10-05 18:21:25 +0200388 if vim_tenant['config'].get('admin_password'):
389 vim_tenant['config']['admin_password'] = "******"
390 if vim_tenant['config'].get('vcenter_password'):
391 vim_tenant['config']['vcenter_password'] = "******"
392 if vim_tenant['config'].get('nsx_password'):
393 vim_tenant['config']['nsx_password'] = "******"
venkatamahesh6ecca182017-01-27 23:04:40 +0530394 except Exception as e:
tierno8008c3a2016-10-13 15:34:28 +0000395 logger.error("Exception '%s' while trying to load config information", str(e))
396
tiernof97fd272016-07-11 14:32:37 +0200397 if datacenter['config'] != None:
398 try:
399 config_dict = yaml.load(datacenter['config'])
400 datacenter['config'] = config_dict
gcalvinoc62cfa52017-10-05 18:21:25 +0200401 if datacenter['config'].get('admin_password'):
402 datacenter['config']['admin_password'] = "******"
403 if datacenter['config'].get('vcenter_password'):
404 datacenter['config']['vcenter_password'] = "******"
405 if datacenter['config'].get('nsx_password'):
406 datacenter['config']['nsx_password'] = "******"
venkatamahesh6ecca182017-01-27 23:04:40 +0530407 except Exception as e:
tiernoefd80c92016-09-16 14:17:46 +0200408 logger.error("Exception '%s' while trying to load config information", str(e))
tiernof97fd272016-07-11 14:32:37 +0200409 #change_keys_http2db(content, http2db_datacenter, reverse=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100410 utils.convert_float_timestamp2str(datacenter)
tiernof97fd272016-07-11 14:32:37 +0200411 data={'datacenter' : datacenter}
412 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +0200413 except bottle.HTTPError:
414 raise
tiernof97fd272016-07-11 14:32:37 +0200415 except (nfvo.NfvoException, db_base_Exception) as e:
416 logger.error("http_get_datacenter_id error {}: {}".format(e.http_code, str(e)))
417 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000418 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000419 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100420 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +0000421
tierno7edb6752016-03-21 17:37:52 +0100422
423@bottle.route(url_base + '/datacenters', method='POST')
424def http_post_datacenters():
garciadeblasc27b0462017-03-22 18:57:47 +0100425 '''insert a datacenter into the catalogue. '''
tierno7edb6752016-03-21 17:37:52 +0100426 #parse input data
tiernof97fd272016-07-11 14:32:37 +0200427 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
gcalvinoc62cfa52017-10-05 18:21:25 +0200428 http_content,_ = format_in(datacenter_schema, confidential_data=True)
tierno42fcc3b2016-07-06 17:20:40 +0200429 r = utils.remove_extra_items(http_content, datacenter_schema)
tiernoefd80c92016-09-16 14:17:46 +0200430 if r:
431 logger.debug("Remove received extra items %s", str(r))
tiernof97fd272016-07-11 14:32:37 +0200432 try:
433 data = nfvo.new_datacenter(mydb, http_content['datacenter'])
tierno7edb6752016-03-21 17:37:52 +0100434 return http_get_datacenter_id('any', data)
tiernod2b560b2017-10-11 10:30:18 +0200435 except bottle.HTTPError:
436 raise
tiernof97fd272016-07-11 14:32:37 +0200437 except (nfvo.NfvoException, db_base_Exception) as e:
438 logger.error("http_post_datacenters error {}: {}".format(e.http_code, str(e)))
439 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000440 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000441 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100442 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +0000443
tierno7edb6752016-03-21 17:37:52 +0100444
445@bottle.route(url_base + '/datacenters/<datacenter_id_name>', method='PUT')
446def http_edit_datacenter_id(datacenter_id_name):
447 '''edit datacenter details, can use both uuid or name'''
tiernof97fd272016-07-11 14:32:37 +0200448 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno7edb6752016-03-21 17:37:52 +0100449 #parse input data
450 http_content,_ = format_in( datacenter_edit_schema )
tierno42fcc3b2016-07-06 17:20:40 +0200451 r = utils.remove_extra_items(http_content, datacenter_edit_schema)
tiernoefd80c92016-09-16 14:17:46 +0200452 if r:
453 logger.debug("Remove received extra items %s", str(r))
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100454
tiernof97fd272016-07-11 14:32:37 +0200455 try:
456 datacenter_id = nfvo.edit_datacenter(mydb, datacenter_id_name, http_content['datacenter'])
tierno7edb6752016-03-21 17:37:52 +0100457 return http_get_datacenter_id('any', datacenter_id)
tiernod2b560b2017-10-11 10:30:18 +0200458 except bottle.HTTPError:
459 raise
tiernof97fd272016-07-11 14:32:37 +0200460 except (nfvo.NfvoException, db_base_Exception) as e:
461 logger.error("http_edit_datacenter_id error {}: {}".format(e.http_code, str(e)))
462 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000463 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000464 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100465 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +0000466
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100467@bottle.route(url_base + '/<tenant_id>/sdn_controllers', method='POST')
468def http_post_sdn_controller(tenant_id):
469 '''insert a sdn controller into the catalogue. '''
470 #parse input data
471 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
472 http_content,_ = format_in( sdn_controller_schema )
473 try:
474 logger.debug("tenant_id: "+tenant_id)
475 #logger.debug("content: {}".format(http_content['sdn_controller']))
476
477 data = nfvo.sdn_controller_create(mydb, tenant_id, http_content['sdn_controller'])
478 return format_out({"sdn_controller": nfvo.sdn_controller_list(mydb, tenant_id, data)})
tiernod2b560b2017-10-11 10:30:18 +0200479 except bottle.HTTPError:
480 raise
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100481 except (nfvo.NfvoException, db_base_Exception) as e:
482 logger.error("http_post_sdn_controller error {}: {}".format(e.http_code, str(e)))
483 bottle.abort(e.http_code, str(e))
484 except Exception as e:
485 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100486 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100487
488@bottle.route(url_base + '/<tenant_id>/sdn_controllers/<controller_id>', method='PUT')
489def http_put_sdn_controller_update(tenant_id, controller_id):
490 '''Update sdn controller'''
491 #parse input data
492 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
493 http_content,_ = format_in( sdn_controller_edit_schema )
494# r = utils.remove_extra_items(http_content, datacenter_schema)
495# if r:
496# logger.debug("Remove received extra items %s", str(r))
497 try:
498 #logger.debug("tenant_id: "+tenant_id)
499 logger.debug("content: {}".format(http_content['sdn_controller']))
500
501 data = nfvo.sdn_controller_update(mydb, tenant_id, controller_id, http_content['sdn_controller'])
502 return format_out({"sdn_controller": nfvo.sdn_controller_list(mydb, tenant_id, controller_id)})
503
tiernod2b560b2017-10-11 10:30:18 +0200504 except bottle.HTTPError:
505 raise
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100506 except (nfvo.NfvoException, db_base_Exception) as e:
507 logger.error("http_post_sdn_controller error {}: {}".format(e.http_code, str(e)))
508 bottle.abort(e.http_code, str(e))
509 except Exception as e:
510 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100511 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100512
513@bottle.route(url_base + '/<tenant_id>/sdn_controllers', method='GET')
514def http_get_sdn_controller(tenant_id):
515 '''get sdn controllers list, can use both uuid or name'''
516 try:
517 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
518
519 data = {'sdn_controllers': nfvo.sdn_controller_list(mydb, tenant_id)}
520 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +0200521 except bottle.HTTPError:
522 raise
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100523 except (nfvo.NfvoException, db_base_Exception) as e:
524 logger.error("http_get_sdn_controller error {}: {}".format(e.http_code, str(e)))
525 bottle.abort(e.http_code, str(e))
526 except Exception as e:
527 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100528 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100529
530@bottle.route(url_base + '/<tenant_id>/sdn_controllers/<controller_id>', method='GET')
531def http_get_sdn_controller_id(tenant_id, controller_id):
532 '''get sdn controller details, can use both uuid or name'''
533 try:
534 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
535 data = nfvo.sdn_controller_list(mydb, tenant_id, controller_id)
536 return format_out({"sdn_controllers": data})
tiernod2b560b2017-10-11 10:30:18 +0200537 except bottle.HTTPError:
538 raise
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100539 except (nfvo.NfvoException, db_base_Exception) as e:
540 logger.error("http_get_sdn_controller_id error {}: {}".format(e.http_code, str(e)))
541 bottle.abort(e.http_code, str(e))
542 except Exception as e:
543 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100544 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100545
546@bottle.route(url_base + '/<tenant_id>/sdn_controllers/<controller_id>', method='DELETE')
547def http_delete_sdn_controller_id(tenant_id, controller_id):
548 '''delete sdn controller, can use both uuid or name'''
549 try:
550 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
551 data = nfvo.sdn_controller_delete(mydb, tenant_id, controller_id)
552 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +0200553 except bottle.HTTPError:
554 raise
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100555 except (nfvo.NfvoException, db_base_Exception) as e:
556 logger.error("http_delete_sdn_controller_id error {}: {}".format(e.http_code, str(e)))
557 bottle.abort(e.http_code, str(e))
558 except Exception as e:
559 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100560 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100561
562@bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/sdn_mapping', method='POST')
563def http_post_datacenter_sdn_port_mapping(tenant_id, datacenter_id):
564 '''Set the sdn port mapping for a datacenter. '''
565 #parse input data
566 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
567 http_content, _ = format_in(sdn_port_mapping_schema)
568# r = utils.remove_extra_items(http_content, datacenter_schema)
569# if r:
570# logger.debug("Remove received extra items %s", str(r))
571 try:
572 data = nfvo.datacenter_sdn_port_mapping_set(mydb, tenant_id, datacenter_id, http_content['sdn_port_mapping'])
573 return format_out({"sdn_port_mapping": data})
tiernod2b560b2017-10-11 10:30:18 +0200574 except bottle.HTTPError:
575 raise
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100576 except (nfvo.NfvoException, db_base_Exception) as e:
577 logger.error("http_post_datacenter_sdn_port_mapping error {}: {}".format(e.http_code, str(e)))
578 bottle.abort(e.http_code, str(e))
579 except Exception as e:
580 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100581 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100582
583@bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/sdn_mapping', method='GET')
584def http_get_datacenter_sdn_port_mapping(tenant_id, datacenter_id):
585 '''get datacenter sdn mapping details, can use both uuid or name'''
586 try:
587 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
588
589 data = nfvo.datacenter_sdn_port_mapping_list(mydb, tenant_id, datacenter_id)
590 return format_out({"sdn_port_mapping": data})
tiernod2b560b2017-10-11 10:30:18 +0200591 except bottle.HTTPError:
592 raise
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100593 except (nfvo.NfvoException, db_base_Exception) as e:
594 logger.error("http_get_datacenter_sdn_port_mapping error {}: {}".format(e.http_code, str(e)))
595 bottle.abort(e.http_code, str(e))
596 except Exception as e:
597 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100598 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100599
600@bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/sdn_mapping', method='DELETE')
601def http_delete_datacenter_sdn_port_mapping(tenant_id, datacenter_id):
602 '''clean datacenter sdn mapping, can use both uuid or name'''
603 try:
604 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
605 data = nfvo.datacenter_sdn_port_mapping_delete(mydb, tenant_id, datacenter_id)
606 return format_out({"result": data})
tiernod2b560b2017-10-11 10:30:18 +0200607 except bottle.HTTPError:
608 raise
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100609 except (nfvo.NfvoException, db_base_Exception) as e:
610 logger.error("http_delete_datacenter_sdn_port_mapping error {}: {}".format(e.http_code, str(e)))
611 bottle.abort(e.http_code, str(e))
612 except Exception as e:
613 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100614 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tierno7edb6752016-03-21 17:37:52 +0100615
616@bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/networks', method='GET') #deprecated
617@bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/netmaps', method='GET')
618@bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/netmaps/<netmap_id>', method='GET')
619def http_getnetmap_datacenter_id(tenant_id, datacenter_id, netmap_id=None):
620 '''get datacenter networks, can use both uuid or name'''
tiernof97fd272016-07-11 14:32:37 +0200621 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno7edb6752016-03-21 17:37:52 +0100622 #obtain data
tiernof97fd272016-07-11 14:32:37 +0200623 try:
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100624 datacenter_dict = mydb.get_table_by_uuid_name('datacenters', datacenter_id, "datacenter")
tiernof97fd272016-07-11 14:32:37 +0200625 where_= {"datacenter_id":datacenter_dict['uuid']}
626 if netmap_id:
627 if utils.check_valid_uuid(netmap_id):
628 where_["uuid"] = netmap_id
629 else:
630 where_["name"] = netmap_id
631 netmaps =mydb.get_rows(FROM='datacenter_nets',
632 SELECT=('name','vim_net_id as vim_id', 'uuid', 'type','multipoint','shared','description', 'created_at'),
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100633 WHERE=where_ )
634 utils.convert_float_timestamp2str(netmaps)
tiernof97fd272016-07-11 14:32:37 +0200635 utils.convert_str2boolean(netmaps, ('shared', 'multipoint') )
636 if netmap_id and len(netmaps)==1:
637 data={'netmap' : netmaps[0]}
638 elif netmap_id and len(netmaps)==0:
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100639 bottle.abort(httperrors.Not_Found, "No netmap found with " + " and ".join(map(lambda x: str(x[0])+": "+str(x[1]), where_.iteritems())) )
640 return
tierno7edb6752016-03-21 17:37:52 +0100641 else:
tiernof97fd272016-07-11 14:32:37 +0200642 data={'netmaps' : netmaps}
643 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +0200644 except bottle.HTTPError:
645 raise
tiernof97fd272016-07-11 14:32:37 +0200646 except (nfvo.NfvoException, db_base_Exception) as e:
647 logger.error("http_getnetwork_datacenter_id error {}: {}".format(e.http_code, str(e)))
648 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000649 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000650 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100651 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +0000652
tierno7edb6752016-03-21 17:37:52 +0100653
654@bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/netmaps', method='DELETE')
655@bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/netmaps/<netmap_id>', method='DELETE')
656def http_delnetmap_datacenter_id(tenant_id, datacenter_id, netmap_id=None):
657 '''get datacenter networks, can use both uuid or name'''
tiernof97fd272016-07-11 14:32:37 +0200658 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno7edb6752016-03-21 17:37:52 +0100659 #obtain data
tiernof97fd272016-07-11 14:32:37 +0200660 try:
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100661 datacenter_dict = mydb.get_table_by_uuid_name('datacenters', datacenter_id, "datacenter")
tiernof97fd272016-07-11 14:32:37 +0200662 where_= {"datacenter_id":datacenter_dict['uuid']}
663 if netmap_id:
664 if utils.check_valid_uuid(netmap_id):
665 where_["uuid"] = netmap_id
666 else:
667 where_["name"] = netmap_id
668 #change_keys_http2db(content, http2db_tenant, reverse=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100669 deleted = mydb.delete_row(FROM='datacenter_nets', WHERE= where_)
tiernod2b560b2017-10-11 10:30:18 +0200670 if deleted == 0 and netmap_id:
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100671 bottle.abort(httperrors.Not_Found, "No netmap found with " + " and ".join(map(lambda x: str(x[0])+": "+str(x[1]), where_.iteritems())) )
tiernof97fd272016-07-11 14:32:37 +0200672 if netmap_id:
673 return format_out({"result": "netmap %s deleted" % netmap_id})
tierno7edb6752016-03-21 17:37:52 +0100674 else:
tiernof97fd272016-07-11 14:32:37 +0200675 return format_out({"result": "%d netmap deleted" % deleted})
tiernod2b560b2017-10-11 10:30:18 +0200676 except bottle.HTTPError:
677 raise
tiernof97fd272016-07-11 14:32:37 +0200678 except (nfvo.NfvoException, db_base_Exception) as e:
679 logger.error("http_delnetmap_datacenter_id error {}: {}".format(e.http_code, str(e)))
680 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000681 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000682 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100683 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tierno7edb6752016-03-21 17:37:52 +0100684
685
686@bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/netmaps/upload', method='POST')
687def http_uploadnetmap_datacenter_id(tenant_id, datacenter_id):
tiernof97fd272016-07-11 14:32:37 +0200688 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
689 try:
690 netmaps = nfvo.datacenter_new_netmap(mydb, tenant_id, datacenter_id, None)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100691 utils.convert_float_timestamp2str(netmaps)
tiernof97fd272016-07-11 14:32:37 +0200692 utils.convert_str2boolean(netmaps, ('shared', 'multipoint') )
693 data={'netmaps' : netmaps}
694 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +0200695 except bottle.HTTPError:
696 raise
tiernof97fd272016-07-11 14:32:37 +0200697 except (nfvo.NfvoException, db_base_Exception) as e:
698 logger.error("http_uploadnetmap_datacenter_id error {}: {}".format(e.http_code, str(e)))
699 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000700 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000701 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100702 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +0000703
tierno7edb6752016-03-21 17:37:52 +0100704
705@bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/netmaps', method='POST')
706def http_postnetmap_datacenter_id(tenant_id, datacenter_id):
707 '''creates a new netmap'''
tiernof97fd272016-07-11 14:32:37 +0200708 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno7edb6752016-03-21 17:37:52 +0100709 #parse input data
710 http_content,_ = format_in( netmap_new_schema )
tierno42fcc3b2016-07-06 17:20:40 +0200711 r = utils.remove_extra_items(http_content, netmap_new_schema)
tiernoefd80c92016-09-16 14:17:46 +0200712 if r:
713 logger.debug("Remove received extra items %s", str(r))
tiernof97fd272016-07-11 14:32:37 +0200714 try:
715 #obtain data, check that only one exist
716 netmaps = nfvo.datacenter_new_netmap(mydb, tenant_id, datacenter_id, http_content)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100717 utils.convert_float_timestamp2str(netmaps)
tiernof97fd272016-07-11 14:32:37 +0200718 utils.convert_str2boolean(netmaps, ('shared', 'multipoint') )
719 data={'netmaps' : netmaps}
720 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +0200721 except bottle.HTTPError:
722 raise
tiernof97fd272016-07-11 14:32:37 +0200723 except (nfvo.NfvoException, db_base_Exception) as e:
724 logger.error("http_postnetmap_datacenter_id error {}: {}".format(e.http_code, str(e)))
725 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000726 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000727 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100728 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +0000729
tierno7edb6752016-03-21 17:37:52 +0100730
731@bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/netmaps/<netmap_id>', method='PUT')
732def http_putnettmap_datacenter_id(tenant_id, datacenter_id, netmap_id):
733 '''edit a netmap'''
tiernof97fd272016-07-11 14:32:37 +0200734 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno7edb6752016-03-21 17:37:52 +0100735 #parse input data
736 http_content,_ = format_in( netmap_edit_schema )
tierno42fcc3b2016-07-06 17:20:40 +0200737 r = utils.remove_extra_items(http_content, netmap_edit_schema)
tiernoefd80c92016-09-16 14:17:46 +0200738 if r:
739 logger.debug("Remove received extra items %s", str(r))
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100740
tierno7edb6752016-03-21 17:37:52 +0100741 #obtain data, check that only one exist
tiernof97fd272016-07-11 14:32:37 +0200742 try:
743 nfvo.datacenter_edit_netmap(mydb, tenant_id, datacenter_id, netmap_id, http_content)
tierno7edb6752016-03-21 17:37:52 +0100744 return http_getnetmap_datacenter_id(tenant_id, datacenter_id, netmap_id)
tiernod2b560b2017-10-11 10:30:18 +0200745 except bottle.HTTPError:
746 raise
tiernof97fd272016-07-11 14:32:37 +0200747 except (nfvo.NfvoException, db_base_Exception) as e:
748 logger.error("http_putnettmap_datacenter_id error {}: {}".format(e.http_code, str(e)))
749 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000750 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000751 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100752 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
753
tierno7edb6752016-03-21 17:37:52 +0100754
755@bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>/action', method='POST')
756def http_action_datacenter_id(tenant_id, datacenter_id):
757 '''perform an action over datacenter, can use both uuid or name'''
tiernof97fd272016-07-11 14:32:37 +0200758 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno7edb6752016-03-21 17:37:52 +0100759 #parse input data
760 http_content,_ = format_in( datacenter_action_schema )
tierno42fcc3b2016-07-06 17:20:40 +0200761 r = utils.remove_extra_items(http_content, datacenter_action_schema)
tiernoefd80c92016-09-16 14:17:46 +0200762 if r:
763 logger.debug("Remove received extra items %s", str(r))
tiernof97fd272016-07-11 14:32:37 +0200764 try:
765 #obtain data, check that only one exist
766 result = nfvo.datacenter_action(mydb, tenant_id, datacenter_id, http_content)
767 if 'net-update' in http_content:
768 return http_getnetmap_datacenter_id(datacenter_id)
769 else:
770 return format_out(result)
tiernod2b560b2017-10-11 10:30:18 +0200771 except bottle.HTTPError:
772 raise
tiernof97fd272016-07-11 14:32:37 +0200773 except (nfvo.NfvoException, db_base_Exception) as e:
774 logger.error("http_action_datacenter_id error {}: {}".format(e.http_code, str(e)))
775 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000776 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000777 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100778 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tierno7edb6752016-03-21 17:37:52 +0100779
780
781@bottle.route(url_base + '/datacenters/<datacenter_id>', method='DELETE')
782def http_delete_datacenter_id( datacenter_id):
783 '''delete a tenant from database, can use both uuid or name'''
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100784
tiernof97fd272016-07-11 14:32:37 +0200785 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
786 try:
787 data = nfvo.delete_datacenter(mydb, datacenter_id)
788 return format_out({"result":"datacenter '" + data + "' deleted"})
tiernod2b560b2017-10-11 10:30:18 +0200789 except bottle.HTTPError:
790 raise
tiernof97fd272016-07-11 14:32:37 +0200791 except (nfvo.NfvoException, db_base_Exception) as e:
792 logger.error("http_delete_datacenter_id error {}: {}".format(e.http_code, str(e)))
793 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000794 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000795 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100796 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +0000797
tierno7edb6752016-03-21 17:37:52 +0100798
799@bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>', method='POST')
tiernod3750b32018-07-20 15:33:08 +0200800@bottle.route(url_base + '/<tenant_id>/vim_accounts', method='POST')
801def http_associate_datacenters(tenant_id, datacenter_id=None):
tierno7edb6752016-03-21 17:37:52 +0100802 '''associate an existing datacenter to a this tenant. '''
tiernof97fd272016-07-11 14:32:37 +0200803 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno7edb6752016-03-21 17:37:52 +0100804 #parse input data
gcalvinoc62cfa52017-10-05 18:21:25 +0200805 http_content,_ = format_in(datacenter_associate_schema, confidential_data=True)
tierno42fcc3b2016-07-06 17:20:40 +0200806 r = utils.remove_extra_items(http_content, datacenter_associate_schema)
tiernoefd80c92016-09-16 14:17:46 +0200807 if r:
808 logger.debug("Remove received extra items %s", str(r))
tiernof97fd272016-07-11 14:32:37 +0200809 try:
tiernod3750b32018-07-20 15:33:08 +0200810 vim_account_id = nfvo.create_vim_account(mydb, tenant_id, datacenter_id,
811 **http_content['datacenter'])
812 return http_get_vim_account(tenant_id, vim_account_id)
tiernod2b560b2017-10-11 10:30:18 +0200813 except bottle.HTTPError:
814 raise
tiernof97fd272016-07-11 14:32:37 +0200815 except (nfvo.NfvoException, db_base_Exception) as e:
816 logger.error("http_associate_datacenters error {}: {}".format(e.http_code, str(e)))
817 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000818 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000819 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100820 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +0000821
tiernod3750b32018-07-20 15:33:08 +0200822@bottle.route(url_base + '/<tenant_id>/vim_accounts/<vim_account_id>', method='PUT')
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100823@bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>', method='PUT')
tiernod3750b32018-07-20 15:33:08 +0200824def http_vim_account_edit(tenant_id, vim_account_id=None, datacenter_id=None):
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100825 '''associate an existing datacenter to a this tenant. '''
826 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
827 #parse input data
tiernod3750b32018-07-20 15:33:08 +0200828 http_content,_ = format_in(datacenter_associate_schema)
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100829 r = utils.remove_extra_items(http_content, datacenter_associate_schema)
830 if r:
831 logger.debug("Remove received extra items %s", str(r))
832 try:
tiernod3750b32018-07-20 15:33:08 +0200833 vim_account_id = nfvo.edit_vim_account(mydb, tenant_id, vim_account_id, datacenter_id=datacenter_id,
834 **http_content['datacenter'])
835 return http_get_vim_account(tenant_id, vim_account_id)
tiernod2b560b2017-10-11 10:30:18 +0200836 except bottle.HTTPError:
837 raise
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100838 except (nfvo.NfvoException, db_base_Exception) as e:
tiernod3750b32018-07-20 15:33:08 +0200839 logger.error("http_vim_account_edit error {}: {}".format(e.http_code, str(e)))
Pablo Montes Moreno3fbff9b2017-03-08 11:28:15 +0100840 bottle.abort(e.http_code, str(e))
841 except Exception as e:
842 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100843 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tierno7edb6752016-03-21 17:37:52 +0100844
tiernod3750b32018-07-20 15:33:08 +0200845
tierno7edb6752016-03-21 17:37:52 +0100846@bottle.route(url_base + '/<tenant_id>/datacenters/<datacenter_id>', method='DELETE')
tiernod3750b32018-07-20 15:33:08 +0200847@bottle.route(url_base + '/<tenant_id>/vim_accounts/<vim_account_id>', method='DELETE')
848def http_deassociate_datacenters(tenant_id, datacenter_id=None, vim_account_id=None):
tierno7edb6752016-03-21 17:37:52 +0100849 '''deassociate an existing datacenter to a this tenant. '''
tiernof97fd272016-07-11 14:32:37 +0200850 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
851 try:
tiernod3750b32018-07-20 15:33:08 +0200852 data = nfvo.delete_vim_account(mydb, tenant_id, vim_account_id, datacenter_id)
tiernof97fd272016-07-11 14:32:37 +0200853 return format_out({"result": data})
tiernod2b560b2017-10-11 10:30:18 +0200854 except bottle.HTTPError:
855 raise
tiernof97fd272016-07-11 14:32:37 +0200856 except (nfvo.NfvoException, db_base_Exception) as e:
857 logger.error("http_deassociate_datacenters error {}: {}".format(e.http_code, str(e)))
858 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000859 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000860 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100861 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +0000862
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +0200863@bottle.route(url_base + '/<tenant_id>/vim/<datacenter_id>/network/<network_id>/attach', method='POST')
864def http_post_vim_net_sdn_attach(tenant_id, datacenter_id, network_id):
865 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
866 http_content, _ = format_in(sdn_external_port_schema)
867 try:
868 data = nfvo.vim_net_sdn_attach(mydb, tenant_id, datacenter_id, network_id, http_content)
869 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +0200870 except bottle.HTTPError:
871 raise
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +0200872 except (nfvo.NfvoException, db_base_Exception) as e:
873 logger.error("http_post_vim_net_sdn_attach error {}: {}".format(e.http_code, str(e)))
874 bottle.abort(e.http_code, str(e))
875 except Exception as e:
876 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100877 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +0200878
879@bottle.route(url_base + '/<tenant_id>/vim/<datacenter_id>/network/<network_id>/detach', method='DELETE')
880@bottle.route(url_base + '/<tenant_id>/vim/<datacenter_id>/network/<network_id>/detach/<port_id>', method='DELETE')
881def http_delete_vim_net_sdn_detach(tenant_id, datacenter_id, network_id, port_id=None):
882 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
883 try:
884 data = nfvo.vim_net_sdn_detach(mydb, tenant_id, datacenter_id, network_id, port_id)
885 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +0200886 except bottle.HTTPError:
887 raise
Pablo Montes Moreno6aa0b2b2017-05-23 18:33:12 +0200888 except (nfvo.NfvoException, db_base_Exception) as e:
889 logger.error("http_delete_vim_net_sdn_detach error {}: {}".format(e.http_code, str(e)))
890 bottle.abort(e.http_code, str(e))
891 except Exception as e:
892 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100893 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
894
tierno7edb6752016-03-21 17:37:52 +0100895@bottle.route(url_base + '/<tenant_id>/vim/<datacenter_id>/<item>', method='GET')
896@bottle.route(url_base + '/<tenant_id>/vim/<datacenter_id>/<item>/<name>', method='GET')
897def http_get_vim_items(tenant_id, datacenter_id, item, name=None):
tiernof97fd272016-07-11 14:32:37 +0200898 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
899 try:
900 data = nfvo.vim_action_get(mydb, tenant_id, datacenter_id, item, name)
tierno7edb6752016-03-21 17:37:52 +0100901 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +0200902 except bottle.HTTPError:
903 raise
tiernof97fd272016-07-11 14:32:37 +0200904 except (nfvo.NfvoException, db_base_Exception) as e:
905 logger.error("http_get_vim_items error {}: {}".format(e.http_code, str(e)))
906 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000907 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000908 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100909 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +0000910
tierno7edb6752016-03-21 17:37:52 +0100911
912@bottle.route(url_base + '/<tenant_id>/vim/<datacenter_id>/<item>/<name>', method='DELETE')
913def http_del_vim_items(tenant_id, datacenter_id, item, name):
tiernof97fd272016-07-11 14:32:37 +0200914 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
915 try:
916 data = nfvo.vim_action_delete(mydb, tenant_id, datacenter_id, item, name)
tierno7edb6752016-03-21 17:37:52 +0100917 return format_out({"result":data})
tiernod2b560b2017-10-11 10:30:18 +0200918 except bottle.HTTPError:
919 raise
tiernof97fd272016-07-11 14:32:37 +0200920 except (nfvo.NfvoException, db_base_Exception) as e:
921 logger.error("http_del_vim_items error {}: {}".format(e.http_code, str(e)))
922 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000923 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000924 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100925 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +0000926
tierno65a9b0c2016-09-28 14:57:25 +0000927
tierno7edb6752016-03-21 17:37:52 +0100928@bottle.route(url_base + '/<tenant_id>/vim/<datacenter_id>/<item>', method='POST')
929def http_post_vim_items(tenant_id, datacenter_id, item):
tiernof97fd272016-07-11 14:32:37 +0200930 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno7edb6752016-03-21 17:37:52 +0100931 http_content,_ = format_in( object_schema )
tiernof97fd272016-07-11 14:32:37 +0200932 try:
933 data = nfvo.vim_action_create(mydb, tenant_id, datacenter_id, item, http_content)
tierno7edb6752016-03-21 17:37:52 +0100934 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +0200935 except bottle.HTTPError:
936 raise
tiernof97fd272016-07-11 14:32:37 +0200937 except (nfvo.NfvoException, db_base_Exception) as e:
938 logger.error("http_post_vim_items error {}: {}".format(e.http_code, str(e)))
939 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000940 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000941 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100942 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +0000943
tierno7edb6752016-03-21 17:37:52 +0100944
945@bottle.route(url_base + '/<tenant_id>/vnfs', method='GET')
946def http_get_vnfs(tenant_id):
tiernof97fd272016-07-11 14:32:37 +0200947 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
948 try:
949 if tenant_id != 'any':
950 #check valid tenant_id
951 nfvo.check_tenant(mydb, tenant_id)
952 select_,where_,limit_ = filter_query_string(bottle.request.query, None,
tiernof1ba57e2017-09-07 12:23:19 +0200953 ('uuid', 'name', 'osm_id', 'description', 'public', "tenant_id", "created_at") )
tiernof97fd272016-07-11 14:32:37 +0200954 if tenant_id != "any":
tierno3fcfdb72017-10-24 07:48:24 +0200955 where_["OR"]={"tenant_id": tenant_id, "public": True}
956 vnfs = mydb.get_rows(FROM='vnfs', SELECT=select_, WHERE=where_, LIMIT=limit_)
957 # change_keys_http2db(content, http2db_vnf, reverse=True)
tiernof97fd272016-07-11 14:32:37 +0200958 utils.convert_str2boolean(vnfs, ('public',))
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100959 utils.convert_float_timestamp2str(vnfs)
tierno3fcfdb72017-10-24 07:48:24 +0200960 data={'vnfs': vnfs}
tierno7edb6752016-03-21 17:37:52 +0100961 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +0200962 except bottle.HTTPError:
963 raise
tiernof97fd272016-07-11 14:32:37 +0200964 except (nfvo.NfvoException, db_base_Exception) as e:
965 logger.error("http_get_vnfs error {}: {}".format(e.http_code, str(e)))
966 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000967 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000968 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100969 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +0000970
tierno7edb6752016-03-21 17:37:52 +0100971
972@bottle.route(url_base + '/<tenant_id>/vnfs/<vnf_id>', method='GET')
973def http_get_vnf_id(tenant_id,vnf_id):
974 '''get vnf details, can use both uuid or name'''
tiernof97fd272016-07-11 14:32:37 +0200975 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
976 try:
977 vnf = nfvo.get_vnf_id(mydb,tenant_id,vnf_id)
978 utils.convert_str2boolean(vnf, ('public',))
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100979 utils.convert_float_timestamp2str(vnf)
tiernof97fd272016-07-11 14:32:37 +0200980 return format_out(vnf)
tiernod2b560b2017-10-11 10:30:18 +0200981 except bottle.HTTPError:
982 raise
tiernof97fd272016-07-11 14:32:37 +0200983 except (nfvo.NfvoException, db_base_Exception) as e:
984 logger.error("http_get_vnf_id error {}: {}".format(e.http_code, str(e)))
985 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +0000986 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +0000987 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +0100988 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +0000989
tierno7edb6752016-03-21 17:37:52 +0100990
991@bottle.route(url_base + '/<tenant_id>/vnfs', method='POST')
992def http_post_vnfs(tenant_id):
tiernof1ba57e2017-09-07 12:23:19 +0200993 """ Insert a vnf into the catalogue. Creates the flavor and images, and fill the tables at database
994 :param tenant_id: tenant that this vnf belongs to
995 :return:
996 """
997 # print "Parsing the YAML file of the VNF"
998 # parse input data
tiernof97fd272016-07-11 14:32:37 +0200999 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
garciadeblas9f8456e2016-09-05 05:02:59 +02001000 http_content, used_schema = format_in( vnfd_schema_v01, ("schema_version",), {"0.2": vnfd_schema_v02})
tierno42fcc3b2016-07-06 17:20:40 +02001001 r = utils.remove_extra_items(http_content, used_schema)
tiernoefd80c92016-09-16 14:17:46 +02001002 if r:
1003 logger.debug("Remove received extra items %s", str(r))
tiernof97fd272016-07-11 14:32:37 +02001004 try:
tierno4319dad2016-09-05 12:11:11 +02001005 if used_schema == vnfd_schema_v01:
garciadeblas9f8456e2016-09-05 05:02:59 +02001006 vnf_id = nfvo.new_vnf(mydb,tenant_id,http_content)
tierno4319dad2016-09-05 12:11:11 +02001007 elif used_schema == vnfd_schema_v02:
garciadeblas9f8456e2016-09-05 05:02:59 +02001008 vnf_id = nfvo.new_vnf_v02(mydb,tenant_id,http_content)
1009 else:
1010 logger.warning('Unexpected schema_version: %s', http_content.get("schema_version"))
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001011 bottle.abort(httperrors.Bad_Request, "Invalid schema version")
tiernof97fd272016-07-11 14:32:37 +02001012 return http_get_vnf_id(tenant_id, vnf_id)
tiernod2b560b2017-10-11 10:30:18 +02001013 except bottle.HTTPError:
1014 raise
tiernof97fd272016-07-11 14:32:37 +02001015 except (nfvo.NfvoException, db_base_Exception) as e:
1016 logger.error("http_post_vnfs error {}: {}".format(e.http_code, str(e)))
1017 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +00001018 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +00001019 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001020 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +00001021
tiernof1ba57e2017-09-07 12:23:19 +02001022
1023@bottle.route(url_base + '/v3/<tenant_id>/vnfd', method='POST')
1024def http_post_vnfs_v3(tenant_id):
1025 """
1026 Insert one or several VNFs in the catalog, following OSM IM
1027 :param tenant_id: tenant owner of the VNF
1028 :return: The detailed list of inserted VNFs, following the old format
1029 """
1030 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
1031 http_content, _ = format_in(None)
1032 try:
1033 vnfd_uuid_list = nfvo.new_vnfd_v3(mydb, tenant_id, http_content)
1034 vnfd_list = []
1035 for vnfd_uuid in vnfd_uuid_list:
1036 vnf = nfvo.get_vnf_id(mydb, tenant_id, vnfd_uuid)
1037 utils.convert_str2boolean(vnf, ('public',))
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001038 utils.convert_float_timestamp2str(vnf)
tiernof1ba57e2017-09-07 12:23:19 +02001039 vnfd_list.append(vnf["vnf"])
1040 return format_out({"vnfd": vnfd_list})
tiernod2b560b2017-10-11 10:30:18 +02001041 except bottle.HTTPError:
1042 raise
tiernof1ba57e2017-09-07 12:23:19 +02001043 except (nfvo.NfvoException, db_base_Exception) as e:
1044 logger.error("http_post_vnfs error {}: {}".format(e.http_code, str(e)))
1045 bottle.abort(e.http_code, str(e))
1046 except Exception as e:
1047 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001048 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tiernof1ba57e2017-09-07 12:23:19 +02001049
tierno7edb6752016-03-21 17:37:52 +01001050@bottle.route(url_base + '/<tenant_id>/vnfs/<vnf_id>', method='DELETE')
tiernof1ba57e2017-09-07 12:23:19 +02001051def http_delete_vnf_id(tenant_id, vnf_id):
tierno7edb6752016-03-21 17:37:52 +01001052 '''delete a vnf from database, and images and flavors in VIM when appropriate, can use both uuid or name'''
tiernof97fd272016-07-11 14:32:37 +02001053 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001054 #check valid tenant_id and deletes the vnf, including images,
tiernof97fd272016-07-11 14:32:37 +02001055 try:
1056 data = nfvo.delete_vnf(mydb,tenant_id,vnf_id)
tierno7edb6752016-03-21 17:37:52 +01001057 #print json.dumps(data, indent=4)
1058 return format_out({"result":"VNF " + data + " deleted"})
tiernod2b560b2017-10-11 10:30:18 +02001059 except bottle.HTTPError:
1060 raise
tiernof97fd272016-07-11 14:32:37 +02001061 except (nfvo.NfvoException, db_base_Exception) as e:
1062 logger.error("http_delete_vnf_id error {}: {}".format(e.http_code, str(e)))
1063 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +00001064 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +00001065 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001066 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +00001067
tierno7edb6752016-03-21 17:37:52 +01001068
1069#@bottle.route(url_base + '/<tenant_id>/hosts/topology', method='GET')
1070#@bottle.route(url_base + '/<tenant_id>/physicalview/Madrid-Alcantara', method='GET')
1071@bottle.route(url_base + '/<tenant_id>/physicalview/<datacenter>', method='GET')
1072def http_get_hosts(tenant_id, datacenter):
1073 '''get the tidvim host hopology from the vim.'''
tiernof97fd272016-07-11 14:32:37 +02001074 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
1075 #print "http_get_hosts received by tenant " + tenant_id + ' datacenter ' + datacenter
1076 try:
1077 if datacenter == 'treeview':
1078 data = nfvo.get_hosts(mydb, tenant_id)
1079 else:
1080 #openmano-gui is using a hardcoded value for the datacenter
1081 result, data = nfvo.get_hosts_info(mydb, tenant_id) #, datacenter)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001082
tiernof97fd272016-07-11 14:32:37 +02001083 if result < 0:
tiernoefd80c92016-09-16 14:17:46 +02001084 #print "http_get_hosts error %d %s" % (-result, data)
tiernof97fd272016-07-11 14:32:37 +02001085 bottle.abort(-result, data)
1086 else:
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001087 utils.convert_float_timestamp2str(data)
tiernoefd80c92016-09-16 14:17:46 +02001088 #print json.dumps(data, indent=4)
tiernof97fd272016-07-11 14:32:37 +02001089 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +02001090 except bottle.HTTPError:
1091 raise
tiernof97fd272016-07-11 14:32:37 +02001092 except (nfvo.NfvoException, db_base_Exception) as e:
garciadeblas9f8456e2016-09-05 05:02:59 +02001093 logger.error("http_get_hosts error {}: {}".format(e.http_code, str(e)))
tiernof97fd272016-07-11 14:32:37 +02001094 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +00001095 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +00001096 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001097 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tierno7edb6752016-03-21 17:37:52 +01001098
1099
1100@bottle.route(url_base + '/<path:path>', method='OPTIONS')
1101def http_options_deploy(path):
1102 '''For some reason GUI web ask for OPTIONS that must be responded'''
1103 #TODO: check correct path, and correct headers request
tiernof97fd272016-07-11 14:32:37 +02001104 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno7edb6752016-03-21 17:37:52 +01001105 bottle.response.set_header('Access-Control-Allow-Methods','POST, GET, PUT, DELETE, OPTIONS')
1106 bottle.response.set_header('Accept','application/yaml,application/json')
1107 bottle.response.set_header('Content-Type','application/yaml,application/json')
1108 bottle.response.set_header('Access-Control-Allow-Headers','content-type')
1109 bottle.response.set_header('Access-Control-Allow-Origin','*')
1110 return
1111
1112@bottle.route(url_base + '/<tenant_id>/topology/deploy', method='POST')
1113def http_post_deploy(tenant_id):
1114 '''post topology deploy.'''
tiernof97fd272016-07-11 14:32:37 +02001115 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno7edb6752016-03-21 17:37:52 +01001116
tierno66aa0372016-07-06 17:31:12 +02001117 http_content, used_schema = format_in( nsd_schema_v01, ("schema_version",), {2: nsd_schema_v02})
tierno42fcc3b2016-07-06 17:20:40 +02001118 #r = utils.remove_extra_items(http_content, used_schema)
tierno7edb6752016-03-21 17:37:52 +01001119 #if r is not None: print "http_post_deploy: Warning: remove extra items ", r
tiernof97fd272016-07-11 14:32:37 +02001120 #print "http_post_deploy input: ", http_content
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001121
tiernof97fd272016-07-11 14:32:37 +02001122 try:
1123 scenario_id = nfvo.new_scenario(mydb, tenant_id, http_content)
1124 instance = nfvo.start_scenario(mydb, tenant_id, scenario_id, http_content['name'], http_content['name'])
1125 #print json.dumps(data, indent=4)
1126 return format_out(instance)
tiernod2b560b2017-10-11 10:30:18 +02001127 except bottle.HTTPError:
1128 raise
tiernof97fd272016-07-11 14:32:37 +02001129 except (nfvo.NfvoException, db_base_Exception) as e:
1130 logger.error("http_post_deploy error {}: {}".format(e.http_code, str(e)))
1131 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +00001132 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +00001133 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001134 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +00001135
tierno7edb6752016-03-21 17:37:52 +01001136
1137@bottle.route(url_base + '/<tenant_id>/topology/verify', method='POST')
1138def http_post_verify(tenant_id):
1139 #TODO:
1140# '''post topology verify'''
1141# print "http_post_verify by tenant " + tenant_id + ' datacenter ' + datacenter
tiernof97fd272016-07-11 14:32:37 +02001142 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001143 return
tierno7edb6752016-03-21 17:37:52 +01001144
1145#
1146# SCENARIOS
1147#
1148
1149@bottle.route(url_base + '/<tenant_id>/scenarios', method='POST')
1150def http_post_scenarios(tenant_id):
1151 '''add a scenario into the catalogue. Creates the scenario and its internal structure in the OPENMANO DB'''
tiernof97fd272016-07-11 14:32:37 +02001152 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
garciadeblas9f8456e2016-09-05 05:02:59 +02001153 http_content, used_schema = format_in( nsd_schema_v01, ("schema_version",), {2: nsd_schema_v02, "0.3": nsd_schema_v03})
tierno42fcc3b2016-07-06 17:20:40 +02001154 #r = utils.remove_extra_items(http_content, used_schema)
tierno7edb6752016-03-21 17:37:52 +01001155 #if r is not None: print "http_post_scenarios: Warning: remove extra items ", r
tiernof97fd272016-07-11 14:32:37 +02001156 #print "http_post_scenarios input: ", http_content
1157 try:
tierno4319dad2016-09-05 12:11:11 +02001158 if used_schema == nsd_schema_v01:
tiernof97fd272016-07-11 14:32:37 +02001159 scenario_id = nfvo.new_scenario(mydb, tenant_id, http_content)
tierno4319dad2016-09-05 12:11:11 +02001160 elif used_schema == nsd_schema_v02:
tierno5bb59dc2017-02-13 14:53:54 +01001161 scenario_id = nfvo.new_scenario_v02(mydb, tenant_id, http_content, "0.2")
tierno4319dad2016-09-05 12:11:11 +02001162 elif used_schema == nsd_schema_v03:
tierno5bb59dc2017-02-13 14:53:54 +01001163 scenario_id = nfvo.new_scenario_v02(mydb, tenant_id, http_content, "0.3")
garciadeblas9f8456e2016-09-05 05:02:59 +02001164 else:
1165 logger.warning('Unexpected schema_version: %s', http_content.get("schema_version"))
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001166 bottle.abort(httperrors.Bad_Request, "Invalid schema version")
tierno7edb6752016-03-21 17:37:52 +01001167 #print json.dumps(data, indent=4)
1168 #return format_out(data)
tiernof97fd272016-07-11 14:32:37 +02001169 return http_get_scenario_id(tenant_id, scenario_id)
tiernod2b560b2017-10-11 10:30:18 +02001170 except bottle.HTTPError:
1171 raise
tiernof97fd272016-07-11 14:32:37 +02001172 except (nfvo.NfvoException, db_base_Exception) as e:
1173 logger.error("http_post_scenarios error {}: {}".format(e.http_code, str(e)))
1174 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +00001175 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +00001176 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001177 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +00001178
tiernof1ba57e2017-09-07 12:23:19 +02001179@bottle.route(url_base + '/v3/<tenant_id>/nsd', method='POST')
1180def http_post_nsds_v3(tenant_id):
1181 """
1182 Insert one or several NSDs in the catalog, following OSM IM
1183 :param tenant_id: tenant owner of the NSD
1184 :return: The detailed list of inserted NSDs, following the old format
1185 """
1186 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
1187 http_content, _ = format_in(None)
1188 try:
1189 nsd_uuid_list = nfvo.new_nsd_v3(mydb, tenant_id, http_content)
1190 nsd_list = []
1191 for nsd_uuid in nsd_uuid_list:
1192 scenario = mydb.get_scenario(nsd_uuid, tenant_id)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001193 utils.convert_float_timestamp2str(scenario)
tiernof1ba57e2017-09-07 12:23:19 +02001194 nsd_list.append(scenario)
1195 data = {'nsd': nsd_list}
1196 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +02001197 except bottle.HTTPError:
1198 raise
tiernof1ba57e2017-09-07 12:23:19 +02001199 except (nfvo.NfvoException, db_base_Exception) as e:
1200 logger.error("http_post_nsds_v3 error {}: {}".format(e.http_code, str(e)))
1201 bottle.abort(e.http_code, str(e))
1202 except Exception as e:
1203 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001204 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tiernof1ba57e2017-09-07 12:23:19 +02001205
tierno7edb6752016-03-21 17:37:52 +01001206
1207@bottle.route(url_base + '/<tenant_id>/scenarios/<scenario_id>/action', method='POST')
1208def http_post_scenario_action(tenant_id, scenario_id):
1209 '''take an action over a scenario'''
tiernof97fd272016-07-11 14:32:37 +02001210 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno551e5322017-01-19 16:16:26 +01001211 # parse input data
1212 http_content, _ = format_in(scenario_action_schema)
1213 r = utils.remove_extra_items(http_content, scenario_action_schema)
1214 if r:
1215 logger.debug("Remove received extra items %s", str(r))
tiernof97fd272016-07-11 14:32:37 +02001216 try:
tierno551e5322017-01-19 16:16:26 +01001217 # check valid tenant_id
1218 nfvo.check_tenant(mydb, tenant_id)
tiernof97fd272016-07-11 14:32:37 +02001219 if "start" in http_content:
1220 data = nfvo.start_scenario(mydb, tenant_id, scenario_id, http_content['start']['instance_name'], \
1221 http_content['start'].get('description',http_content['start']['instance_name']),
1222 http_content['start'].get('datacenter') )
tierno7edb6752016-03-21 17:37:52 +01001223 return format_out(data)
tiernof97fd272016-07-11 14:32:37 +02001224 elif "deploy" in http_content: #Equivalent to start
1225 data = nfvo.start_scenario(mydb, tenant_id, scenario_id, http_content['deploy']['instance_name'],
1226 http_content['deploy'].get('description',http_content['deploy']['instance_name']),
1227 http_content['deploy'].get('datacenter') )
tierno7edb6752016-03-21 17:37:52 +01001228 return format_out(data)
tiernof97fd272016-07-11 14:32:37 +02001229 elif "reserve" in http_content: #Reserve resources
1230 data = nfvo.start_scenario(mydb, tenant_id, scenario_id, http_content['reserve']['instance_name'],
1231 http_content['reserve'].get('description',http_content['reserve']['instance_name']),
1232 http_content['reserve'].get('datacenter'), startvms=False )
tierno7edb6752016-03-21 17:37:52 +01001233 return format_out(data)
tiernof97fd272016-07-11 14:32:37 +02001234 elif "verify" in http_content: #Equivalent to start and then delete
1235 data = nfvo.start_scenario(mydb, tenant_id, scenario_id, http_content['verify']['instance_name'],
1236 http_content['verify'].get('description',http_content['verify']['instance_name']),
1237 http_content['verify'].get('datacenter'), startvms=False )
1238 instance_id = data['uuid']
1239 nfvo.delete_instance(mydb, tenant_id,instance_id)
tierno7edb6752016-03-21 17:37:52 +01001240 return format_out({"result":"Verify OK"})
tiernod2b560b2017-10-11 10:30:18 +02001241 except bottle.HTTPError:
1242 raise
tiernof97fd272016-07-11 14:32:37 +02001243 except (nfvo.NfvoException, db_base_Exception) as e:
1244 logger.error("http_post_scenario_action error {}: {}".format(e.http_code, str(e)))
1245 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +00001246 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +00001247 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001248 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +00001249
tierno7edb6752016-03-21 17:37:52 +01001250
1251@bottle.route(url_base + '/<tenant_id>/scenarios', method='GET')
1252def http_get_scenarios(tenant_id):
1253 '''get scenarios list'''
tiernof97fd272016-07-11 14:32:37 +02001254 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
1255 try:
1256 #check valid tenant_id
1257 if tenant_id != "any":
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001258 nfvo.check_tenant(mydb, tenant_id)
tiernof97fd272016-07-11 14:32:37 +02001259 #obtain data
tiernof1ba57e2017-09-07 12:23:19 +02001260 s,w,l=filter_query_string(bottle.request.query, None,
1261 ('uuid', 'name', 'osm_id', 'description', 'tenant_id', 'created_at', 'public'))
tiernof97fd272016-07-11 14:32:37 +02001262 if tenant_id != "any":
tierno3fcfdb72017-10-24 07:48:24 +02001263 w["OR"] = {"tenant_id": tenant_id, "public": True}
1264 scenarios = mydb.get_rows(SELECT=s, WHERE=w, LIMIT=l, FROM='scenarios')
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001265 utils.convert_float_timestamp2str(scenarios)
tiernof97fd272016-07-11 14:32:37 +02001266 utils.convert_str2boolean(scenarios, ('public',) )
1267 data={'scenarios':scenarios}
tierno7edb6752016-03-21 17:37:52 +01001268 #print json.dumps(scenarios, indent=4)
tiernof97fd272016-07-11 14:32:37 +02001269 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +02001270 except bottle.HTTPError:
1271 raise
tiernof97fd272016-07-11 14:32:37 +02001272 except (nfvo.NfvoException, db_base_Exception) as e:
1273 logger.error("http_get_scenarios error {}: {}".format(e.http_code, str(e)))
1274 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +00001275 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +00001276 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001277 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +00001278
tierno7edb6752016-03-21 17:37:52 +01001279
1280@bottle.route(url_base + '/<tenant_id>/scenarios/<scenario_id>', method='GET')
1281def http_get_scenario_id(tenant_id, scenario_id):
1282 '''get scenario details, can use both uuid or name'''
tiernof97fd272016-07-11 14:32:37 +02001283 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
1284 try:
1285 #check valid tenant_id
1286 if tenant_id != "any":
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001287 nfvo.check_tenant(mydb, tenant_id)
tiernof97fd272016-07-11 14:32:37 +02001288 #obtain data
1289 scenario = mydb.get_scenario(scenario_id, tenant_id)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001290 utils.convert_float_timestamp2str(scenario)
tiernof97fd272016-07-11 14:32:37 +02001291 data={'scenario' : scenario}
tierno7edb6752016-03-21 17:37:52 +01001292 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +02001293 except bottle.HTTPError:
1294 raise
tiernof97fd272016-07-11 14:32:37 +02001295 except (nfvo.NfvoException, db_base_Exception) as e:
1296 logger.error("http_get_scenarios error {}: {}".format(e.http_code, str(e)))
1297 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +00001298 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +00001299 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001300 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +00001301
tierno7edb6752016-03-21 17:37:52 +01001302
1303@bottle.route(url_base + '/<tenant_id>/scenarios/<scenario_id>', method='DELETE')
1304def http_delete_scenario_id(tenant_id, scenario_id):
1305 '''delete a scenario from database, can use both uuid or name'''
tierno664691a2017-01-31 12:43:46 +01001306 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tiernof97fd272016-07-11 14:32:37 +02001307 try:
1308 #check valid tenant_id
1309 if tenant_id != "any":
tierno664691a2017-01-31 12:43:46 +01001310 nfvo.check_tenant(mydb, tenant_id)
tiernof97fd272016-07-11 14:32:37 +02001311 #obtain data
1312 data = mydb.delete_scenario(scenario_id, tenant_id)
tierno7edb6752016-03-21 17:37:52 +01001313 #print json.dumps(data, indent=4)
1314 return format_out({"result":"scenario " + data + " deleted"})
tiernod2b560b2017-10-11 10:30:18 +02001315 except bottle.HTTPError:
1316 raise
tiernof97fd272016-07-11 14:32:37 +02001317 except (nfvo.NfvoException, db_base_Exception) as e:
1318 logger.error("http_delete_scenario_id error {}: {}".format(e.http_code, str(e)))
1319 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +00001320 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +00001321 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001322 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tierno7edb6752016-03-21 17:37:52 +01001323
1324
1325@bottle.route(url_base + '/<tenant_id>/scenarios/<scenario_id>', method='PUT')
1326def http_put_scenario_id(tenant_id, scenario_id):
1327 '''edit an existing scenario id'''
tiernof97fd272016-07-11 14:32:37 +02001328 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno7edb6752016-03-21 17:37:52 +01001329 http_content,_ = format_in( scenario_edit_schema )
tierno42fcc3b2016-07-06 17:20:40 +02001330 #r = utils.remove_extra_items(http_content, scenario_edit_schema)
tierno7edb6752016-03-21 17:37:52 +01001331 #if r is not None: print "http_put_scenario_id: Warning: remove extra items ", r
tiernof97fd272016-07-11 14:32:37 +02001332 #print "http_put_scenario_id input: ", http_content
1333 try:
1334 nfvo.edit_scenario(mydb, tenant_id, scenario_id, http_content)
tierno7edb6752016-03-21 17:37:52 +01001335 #print json.dumps(data, indent=4)
1336 #return format_out(data)
tiernof97fd272016-07-11 14:32:37 +02001337 return http_get_scenario_id(tenant_id, scenario_id)
tiernod2b560b2017-10-11 10:30:18 +02001338 except bottle.HTTPError:
1339 raise
tiernof97fd272016-07-11 14:32:37 +02001340 except (nfvo.NfvoException, db_base_Exception) as e:
1341 logger.error("http_put_scenario_id error {}: {}".format(e.http_code, str(e)))
1342 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +00001343 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +00001344 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001345 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tierno7edb6752016-03-21 17:37:52 +01001346
1347@bottle.route(url_base + '/<tenant_id>/instances', method='POST')
1348def http_post_instances(tenant_id):
garciadeblasedca7b32016-09-29 14:01:52 +00001349 '''create an instance-scenario'''
tiernof97fd272016-07-11 14:32:37 +02001350 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno551e5322017-01-19 16:16:26 +01001351 # parse input data
1352 http_content, used_schema = format_in(instance_scenario_create_schema_v01)
1353 r = utils.remove_extra_items(http_content, used_schema)
1354 if r is not None:
1355 logger.warning("http_post_instances: Warning: remove extra items %s", str(r))
tiernof97fd272016-07-11 14:32:37 +02001356 try:
1357 #check valid tenant_id
1358 if tenant_id != "any":
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001359 nfvo.check_tenant(mydb, tenant_id)
tiernof97fd272016-07-11 14:32:37 +02001360 data = nfvo.create_instance(mydb, tenant_id, http_content["instance"])
tierno7edb6752016-03-21 17:37:52 +01001361 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +02001362 except bottle.HTTPError:
1363 raise
tiernof97fd272016-07-11 14:32:37 +02001364 except (nfvo.NfvoException, db_base_Exception) as e:
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001365 logger.error("http_post_instances error {}: {}".format(e.http_code, str(e)), exc_info=True)
tiernof97fd272016-07-11 14:32:37 +02001366 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +00001367 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +00001368 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001369 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tierno7edb6752016-03-21 17:37:52 +01001370
1371#
1372# INSTANCES
1373#
1374@bottle.route(url_base + '/<tenant_id>/instances', method='GET')
1375def http_get_instances(tenant_id):
1376 '''get instance list'''
tiernof97fd272016-07-11 14:32:37 +02001377 try:
1378 #check valid tenant_id
1379 if tenant_id != "any":
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001380 nfvo.check_tenant(mydb, tenant_id)
tiernof97fd272016-07-11 14:32:37 +02001381 #obtain data
1382 s,w,l=filter_query_string(bottle.request.query, None, ('uuid', 'name', 'scenario_id', 'tenant_id', 'description', 'created_at'))
1383 if tenant_id != "any":
1384 w['tenant_id'] = tenant_id
1385 instances = mydb.get_rows(SELECT=s, WHERE=w, LIMIT=l, FROM='instance_scenarios')
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001386 utils.convert_float_timestamp2str(instances)
tiernof97fd272016-07-11 14:32:37 +02001387 utils.convert_str2boolean(instances, ('public',) )
1388 data={'instances':instances}
1389 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +02001390 except bottle.HTTPError:
1391 raise
tiernof97fd272016-07-11 14:32:37 +02001392 except (nfvo.NfvoException, db_base_Exception) as e:
1393 logger.error("http_get_instances error {}: {}".format(e.http_code, str(e)))
1394 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +00001395 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +00001396 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001397 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +00001398
tierno7edb6752016-03-21 17:37:52 +01001399
1400@bottle.route(url_base + '/<tenant_id>/instances/<instance_id>', method='GET')
1401def http_get_instance_id(tenant_id, instance_id):
1402 '''get instances details, can use both uuid or name'''
tiernof97fd272016-07-11 14:32:37 +02001403 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
1404 try:
tierno7f426e92018-06-28 15:21:32 +02001405
tiernof97fd272016-07-11 14:32:37 +02001406 #check valid tenant_id
1407 if tenant_id != "any":
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001408 nfvo.check_tenant(mydb, tenant_id)
tiernof97fd272016-07-11 14:32:37 +02001409 if tenant_id == "any":
1410 tenant_id = None
tierno7f426e92018-06-28 15:21:32 +02001411
1412 instance = nfvo.get_instance_id(mydb, tenant_id, instance_id)
1413
tiernof5755962017-07-13 15:44:34 +02001414 # Workaround to SO, convert vnfs:vms:interfaces:ip_address from ";" separated list to report the first value
1415 for vnf in instance.get("vnfs", ()):
1416 for vm in vnf.get("vms", ()):
1417 for iface in vm.get("interfaces", ()):
1418 if iface.get("ip_address"):
1419 index = iface["ip_address"].find(";")
1420 if index >= 0:
1421 iface["ip_address"] = iface["ip_address"][:index]
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001422 utils.convert_float_timestamp2str(instance)
tiernof5755962017-07-13 15:44:34 +02001423 # print json.dumps(instance, indent=4)
tiernof97fd272016-07-11 14:32:37 +02001424 return format_out(instance)
tiernod2b560b2017-10-11 10:30:18 +02001425 except bottle.HTTPError:
1426 raise
tiernof97fd272016-07-11 14:32:37 +02001427 except (nfvo.NfvoException, db_base_Exception) as e:
1428 logger.error("http_get_instance_id error {}: {}".format(e.http_code, str(e)))
1429 bottle.abort(e.http_code, str(e))
tierno8e995ce2016-09-22 08:13:00 +00001430 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +00001431 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001432 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +00001433
tierno7edb6752016-03-21 17:37:52 +01001434
1435@bottle.route(url_base + '/<tenant_id>/instances/<instance_id>', method='DELETE')
1436def http_delete_instance_id(tenant_id, instance_id):
1437 '''delete instance from VIM and from database, can use both uuid or name'''
tiernof97fd272016-07-11 14:32:37 +02001438 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
1439 try:
1440 #check valid tenant_id
1441 if tenant_id != "any":
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001442 nfvo.check_tenant(mydb, tenant_id)
tiernof97fd272016-07-11 14:32:37 +02001443 if tenant_id == "any":
1444 tenant_id = None
1445 #obtain data
1446 message = nfvo.delete_instance(mydb, tenant_id,instance_id)
tierno7edb6752016-03-21 17:37:52 +01001447 return format_out({"result":message})
tiernod2b560b2017-10-11 10:30:18 +02001448 except bottle.HTTPError:
1449 raise
tiernof97fd272016-07-11 14:32:37 +02001450 except (nfvo.NfvoException, db_base_Exception) as e:
1451 logger.error("http_delete_instance_id error {}: {}".format(e.http_code, str(e)))
1452 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +00001453 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +00001454 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001455 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
garciadeblasedca7b32016-09-29 14:01:52 +00001456
tierno7edb6752016-03-21 17:37:52 +01001457
1458@bottle.route(url_base + '/<tenant_id>/instances/<instance_id>/action', method='POST')
1459def http_post_instance_scenario_action(tenant_id, instance_id):
tierno868220c2017-09-26 00:11:05 +02001460 """
1461 take an action over a scenario instance
1462 :param tenant_id: tenant where user belongs to
1463 :param instance_id: instance indentity
1464 :return:
1465 """
tiernof97fd272016-07-11 14:32:37 +02001466 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
tierno551e5322017-01-19 16:16:26 +01001467 # parse input data
1468 http_content, _ = format_in(instance_scenario_action_schema)
1469 r = utils.remove_extra_items(http_content, instance_scenario_action_schema)
1470 if r:
1471 logger.debug("Remove received extra items %s", str(r))
tiernof97fd272016-07-11 14:32:37 +02001472 try:
1473 #check valid tenant_id
1474 if tenant_id != "any":
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001475 nfvo.check_tenant(mydb, tenant_id)
tiernof97fd272016-07-11 14:32:37 +02001476
tiernof97fd272016-07-11 14:32:37 +02001477 #print "http_post_instance_scenario_action input: ", http_content
1478 #obtain data
1479 instance = mydb.get_instance_scenario(instance_id, tenant_id)
1480 instance_id = instance["uuid"]
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001481
tiernof97fd272016-07-11 14:32:37 +02001482 data = nfvo.instance_action(mydb, tenant_id, instance_id, http_content)
tierno7edb6752016-03-21 17:37:52 +01001483 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +02001484 except bottle.HTTPError:
1485 raise
tiernof97fd272016-07-11 14:32:37 +02001486 except (nfvo.NfvoException, db_base_Exception) as e:
1487 logger.error("http_post_instance_scenario_action error {}: {}".format(e.http_code, str(e)))
1488 bottle.abort(e.http_code, str(e))
tierno65a9b0c2016-09-28 14:57:25 +00001489 except Exception as e:
garciadeblasedca7b32016-09-29 14:01:52 +00001490 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001491 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tierno7edb6752016-03-21 17:37:52 +01001492
1493
tierno868220c2017-09-26 00:11:05 +02001494@bottle.route(url_base + '/<tenant_id>/instances/<instance_id>/action', method='GET')
1495@bottle.route(url_base + '/<tenant_id>/instances/<instance_id>/action/<action_id>', method='GET')
1496def http_get_instance_scenario_action(tenant_id, instance_id, action_id=None):
1497 """
1498 List the actions done over an instance, or the action details
1499 :param tenant_id: tenant where user belongs to. Can be "any" to ignore
1500 :param instance_id: instance id, can be "any" to get actions of all instances
1501 :return:
1502 """
1503 logger.debug('FROM %s %s %s', bottle.request.remote_addr, bottle.request.method, bottle.request.url)
1504 try:
1505 # check valid tenant_id
1506 if tenant_id != "any":
1507 nfvo.check_tenant(mydb, tenant_id)
1508 data = nfvo.instance_action_get(mydb, tenant_id, instance_id, action_id)
1509 return format_out(data)
tiernod2b560b2017-10-11 10:30:18 +02001510 except bottle.HTTPError:
1511 raise
tierno868220c2017-09-26 00:11:05 +02001512 except (nfvo.NfvoException, db_base_Exception) as e:
1513 logger.error("http_get_instance_scenario_action error {}: {}".format(e.http_code, str(e)))
1514 bottle.abort(e.http_code, str(e))
1515 except Exception as e:
1516 logger.error("Unexpected exception: ", exc_info=True)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001517 bottle.abort(httperrors.Internal_Server_Error, type(e).__name__ + ": " + str(e))
tierno868220c2017-09-26 00:11:05 +02001518
1519
tierno7edb6752016-03-21 17:37:52 +01001520@bottle.error(400)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001521@bottle.error(401)
1522@bottle.error(404)
tierno7edb6752016-03-21 17:37:52 +01001523@bottle.error(403)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001524@bottle.error(405)
tierno7edb6752016-03-21 17:37:52 +01001525@bottle.error(406)
1526@bottle.error(409)
Anderson Bravalheri0446cd52018-08-17 15:26:19 +01001527@bottle.error(503)
tierno7edb6752016-03-21 17:37:52 +01001528@bottle.error(500)
1529def error400(error):
1530 e={"error":{"code":error.status_code, "type":error.status, "description":error.body}}
1531 bottle.response.headers['Access-Control-Allow-Origin'] = '*'
1532 return format_out(e)
1533