astara-appliance/astara_router/api/v1/system.py

156 lines
4.6 KiB
Python

# Copyright 2014 DreamHost, LLC
#
# Author: DreamHost, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Blueprint for the "system" portion of the version 1 of the API.
"""
from flask import Response
from flask import abort, request
from dogpile.cache import make_region
from astara_router import models
from astara_router import utils
from astara_router import settings
from astara_router.manager import manager
blueprint = utils.blueprint_factory(__name__)
# Managed by _get_cache()
_cache = None
ADVANCED_SERVICES_KEY = 'services'
def _get_cache():
global _cache
if _cache is None:
_cache = make_region().configure(
'dogpile.cache.dbm',
arguments={
"filename": "/tmp/astara-state"
}
)
return _cache
@blueprint.route('/interface/<ifname>')
@utils.json_response
def get_interface(ifname):
'''
Show interface parameters given an interface name.
For example ge1, ge2 for generic ethernet
'''
return dict(interface=manager.router.get_interface(ifname))
@blueprint.route('/interfaces')
@utils.json_response
def get_interfaces():
'''
Show all interfaces and parameters
'''
return dict(interfaces=manager.router.get_interfaces())
@blueprint.route('/config', methods=['GET'])
@utils.json_response
def get_configuration():
"""Return the current router configuration."""
return dict(configuration=manager.config)
@blueprint.route('/config', methods=['PUT'])
@utils.json_response
def put_configuration():
if request.content_type != 'application/json':
abort(415)
try:
system_config_candidate = models.SystemConfiguration(request.json)
except ValueError, e:
return Response(
'The system config failed to deserialize.\n' + str(e),
status=422)
errors = system_config_candidate.validate()
if errors:
return Response(
'The config failed to validate.\n' + '\n'.join(errors),
status=422)
# Config requests to a router appliance will always contain a default ASN,
# so we can key on that for now. Later on we need to move router stuff
# to the extensible list of things the appliance can handle
if request.json.get('asn'):
try:
router_config_candidate = models.RouterConfiguration(request.json)
except ValueError, e:
return Response(
'The router config failed to deserialize.\n' + str(e),
status=422)
errors = router_config_candidate.validate()
if errors:
return Response(
'The config failed to validate.\n' + '\n'.join(errors),
status=422)
else:
router_config_candidate = None
if router_config_candidate:
advanced_service_configs = [router_config_candidate]
else:
advanced_service_configs = []
advanced_services = request.json.get(ADVANCED_SERVICES_KEY, {})
for svc in advanced_services.keys():
if svc not in settings.ENABLED_SERVICES:
return Response(
'This appliance cannot service requested advanced '
'service: %s' % svc, status=400)
for svc in settings.ENABLED_SERVICES:
if not advanced_services.get(svc):
continue
config_model = models.get_config_model(service=svc)
if not config_model:
continue
try:
svc_config_candidate = config_model(advanced_services.get(svc))
except ValueError, e:
return Response(
'The %s config failed to deserialize.\n' + str(e) %
config_model.service_name, status=422)
errors = svc_config_candidate.validate()
if errors:
return Response(
'The %s config failed to validate.\n' + '\n'.join(errors),
config_model.service_name, status=422)
advanced_service_configs.append(svc_config_candidate)
manager.update_config(
system_config=system_config_candidate,
service_configs=advanced_service_configs,
cache=_get_cache())
return dict(configuration=manager.config)