ADMIN_API: Fixes to make admin_api work with current tools
* Hack to get 'usage' routing working * Devices list output needed to be in 'devices' dict * PUT/POST don't wait on gearman so should return 200 instead of 202 * Pool MGM and statsd need to specify json content (WSME is stricter than the Java thing we used) Change-Id: I2fef129ef81045d7b7929e52f09670608c47d801
This commit is contained in:
		@@ -19,16 +19,12 @@ from pecan import expose, response, abort
 | 
			
		||||
from pecan.rest import RestController
 | 
			
		||||
import wsmeext.pecan as wsme_pecan
 | 
			
		||||
from wsme.exc import ClientSideError
 | 
			
		||||
from usage import UsageController
 | 
			
		||||
from libra.admin_api.model.validators import DeviceResp, DevicePost, DevicePut
 | 
			
		||||
from libra.admin_api.model.lbaas import LoadBalancer, Device, session
 | 
			
		||||
from libra.admin_api.model.lbaas import loadbalancers_devices
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DevicesController(RestController):
 | 
			
		||||
 | 
			
		||||
    usage = UsageController()
 | 
			
		||||
 | 
			
		||||
    def __init__(self, devid=None):
 | 
			
		||||
        #  Required for PUT requests. See _lookup() below
 | 
			
		||||
        self.devid = devid
 | 
			
		||||
@@ -55,7 +51,7 @@ class DevicesController(RestController):
 | 
			
		||||
        # if we don't have an id then we want a list of all devices
 | 
			
		||||
        if not device_id:
 | 
			
		||||
            #  return all devices
 | 
			
		||||
            device = []
 | 
			
		||||
            device = {'devices': []}
 | 
			
		||||
 | 
			
		||||
            if marker is None:
 | 
			
		||||
                marker = 0
 | 
			
		||||
@@ -85,10 +81,14 @@ class DevicesController(RestController):
 | 
			
		||||
                    if lbs:
 | 
			
		||||
                        for item in lbs:
 | 
			
		||||
                            lb = item._asdict()
 | 
			
		||||
                            lb['hpcs_tenantid'] = lb['tenantid']
 | 
			
		||||
                            del(lb['tenantid'])
 | 
			
		||||
                            dev['loadBalancers'].append(lb)
 | 
			
		||||
 | 
			
		||||
                device.append(dev)
 | 
			
		||||
                device['devices'].append(dev)
 | 
			
		||||
 | 
			
		||||
        elif device_id == 'usage':
 | 
			
		||||
            return self.usage()
 | 
			
		||||
        else:
 | 
			
		||||
            #  return device detail
 | 
			
		||||
            device = session.query(
 | 
			
		||||
@@ -128,7 +128,7 @@ class DevicesController(RestController):
 | 
			
		||||
        response.status = 200
 | 
			
		||||
        return device
 | 
			
		||||
 | 
			
		||||
    @wsme_pecan.wsexpose(DeviceResp, body=DevicePost, status_code=202)
 | 
			
		||||
    @wsme_pecan.wsexpose(DeviceResp, body=DevicePost)
 | 
			
		||||
    def post(self, body=None):
 | 
			
		||||
        """ Creates a new device entry in devices table.
 | 
			
		||||
        :param None
 | 
			
		||||
@@ -196,7 +196,7 @@ class DevicesController(RestController):
 | 
			
		||||
            session.rollback()
 | 
			
		||||
            raise ClientSideError(errstr)
 | 
			
		||||
 | 
			
		||||
    @wsme_pecan.wsexpose(None, body=DevicePut, status_code=202)
 | 
			
		||||
    @wsme_pecan.wsexpose(None, body=DevicePut)
 | 
			
		||||
    def put(self, body=None):
 | 
			
		||||
        """ Updates a device entry in devices table with new status.
 | 
			
		||||
            Also, updates status of loadbalancers using this device
 | 
			
		||||
@@ -280,7 +280,6 @@ class DevicesController(RestController):
 | 
			
		||||
            session.query(Device).filter(Device.id == device_id).delete()
 | 
			
		||||
            session.flush()
 | 
			
		||||
            session.commit()
 | 
			
		||||
            response.status = 202
 | 
			
		||||
            return None
 | 
			
		||||
        except:
 | 
			
		||||
            logger = logging.getLogger(__name__)
 | 
			
		||||
@@ -291,6 +290,27 @@ class DevicesController(RestController):
 | 
			
		||||
                faultstring="Error deleting device from pool"
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
    # Kludge to get to here because Pecan has a hard time with URL params
 | 
			
		||||
    # and paths
 | 
			
		||||
    def usage(self):
 | 
			
		||||
        """Reports the device usage statistics for total, taken, and free
 | 
			
		||||
            :param None
 | 
			
		||||
            Url:
 | 
			
		||||
                GET /devices/usage
 | 
			
		||||
            Returns: dict
 | 
			
		||||
        """
 | 
			
		||||
        total = session.query(Device).count()
 | 
			
		||||
        free = session.query(Device).filter(Device.status == 'OFFLINE').\
 | 
			
		||||
            count()
 | 
			
		||||
        session.commit()
 | 
			
		||||
        response.status = 200
 | 
			
		||||
 | 
			
		||||
        return dict(
 | 
			
		||||
            total=total,
 | 
			
		||||
            free=free,
 | 
			
		||||
            taken=total - free
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    @expose('json')
 | 
			
		||||
    def _lookup(self, devid, *remainder):
 | 
			
		||||
        """Routes more complex url mapping for PUT
 | 
			
		||||
 
 | 
			
		||||
@@ -1,49 +0,0 @@
 | 
			
		||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 | 
			
		||||
# Copyright 2013 Hewlett-Packard Development Company, L.P.
 | 
			
		||||
#
 | 
			
		||||
# 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.
 | 
			
		||||
 | 
			
		||||
from pecan import expose, response
 | 
			
		||||
from libra.admin_api.model.lbaas import Device, session
 | 
			
		||||
from libra.admin_api.model.responses import Responses
 | 
			
		||||
from pecan.rest import RestController
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UsageController(RestController):
 | 
			
		||||
 | 
			
		||||
    @expose('json')
 | 
			
		||||
    def get(self):
 | 
			
		||||
        """Reports the device usage statistics for total, taken, and free
 | 
			
		||||
            :param None
 | 
			
		||||
            Url:
 | 
			
		||||
                GET /devices/usage
 | 
			
		||||
            Returns: dict
 | 
			
		||||
        """
 | 
			
		||||
        total = session.query(Device).count()
 | 
			
		||||
        free = session.query(Device).filter(Device.status == 'OFFLINE').\
 | 
			
		||||
            count()
 | 
			
		||||
        session.commit()
 | 
			
		||||
        response.status = 200
 | 
			
		||||
 | 
			
		||||
        return dict(
 | 
			
		||||
            total=total,
 | 
			
		||||
            free=free,
 | 
			
		||||
            taken=total - free
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    @expose('json')
 | 
			
		||||
    def _default(self):
 | 
			
		||||
        """default route.. acts as catch all for any wrong urls.
 | 
			
		||||
            For now it returns a 404 because no action is defined for /"""
 | 
			
		||||
        response.status = 404
 | 
			
		||||
        return Responses._default
 | 
			
		||||
@@ -26,6 +26,7 @@ class HPRestDriver(MgmDriver):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, addresses, logger):
 | 
			
		||||
        self.logger = logger
 | 
			
		||||
        self.headers = {'Content-type': 'application/json'}
 | 
			
		||||
        random.shuffle(addresses)
 | 
			
		||||
        for address in addresses:
 | 
			
		||||
            self.url = 'https://{0}/{1}'.format(address, API_VERSION)
 | 
			
		||||
@@ -93,7 +94,10 @@ class HPRestDriver(MgmDriver):
 | 
			
		||||
 | 
			
		||||
    def _post(self, url, node_data):
 | 
			
		||||
        try:
 | 
			
		||||
            r = requests.post(url, data=json.dumps(node_data), verify=False)
 | 
			
		||||
            r = requests.post(
 | 
			
		||||
                url, data=json.dumps(node_data), verify=False,
 | 
			
		||||
                headers=self.headers
 | 
			
		||||
            )
 | 
			
		||||
        except requests.exceptions.RequestException:
 | 
			
		||||
            self.logger.error('Exception communicating to server: {exc}'
 | 
			
		||||
                              .format(exc=sys.exc_info()[0]))
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@ class APIError(Exception):
 | 
			
		||||
class AdminAPI(object):
 | 
			
		||||
    def __init__(self, addresses, logger):
 | 
			
		||||
        self.logger = logger
 | 
			
		||||
        self.headers = {'Content-type': 'application/json'}
 | 
			
		||||
        random.shuffle(addresses)
 | 
			
		||||
        for address in addresses:
 | 
			
		||||
            self.url = 'https://{0}/v1'.format(address)
 | 
			
		||||
@@ -113,7 +114,9 @@ class AdminAPI(object):
 | 
			
		||||
 | 
			
		||||
    def _put(self, url, data):
 | 
			
		||||
        try:
 | 
			
		||||
            r = requests.put(url, data=json.dumps(data), verify=False)
 | 
			
		||||
            r = requests.put(
 | 
			
		||||
                url, data=json.dumps(data), verify=False, headers=self.headers
 | 
			
		||||
            )
 | 
			
		||||
        except requests.exceptions.RequestException:
 | 
			
		||||
            self.logger.exception('Exception communicating to server')
 | 
			
		||||
            return False, None
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user