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:
Andrew Hutchings
2013-06-10 15:34:46 +01:00
parent df060ccd19
commit e7aa11b0d5
4 changed files with 38 additions and 60 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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]))

View File

@@ -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