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
|
from pecan.rest import RestController
|
||||||
import wsmeext.pecan as wsme_pecan
|
import wsmeext.pecan as wsme_pecan
|
||||||
from wsme.exc import ClientSideError
|
from wsme.exc import ClientSideError
|
||||||
from usage import UsageController
|
|
||||||
from libra.admin_api.model.validators import DeviceResp, DevicePost, DevicePut
|
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 LoadBalancer, Device, session
|
||||||
from libra.admin_api.model.lbaas import loadbalancers_devices
|
from libra.admin_api.model.lbaas import loadbalancers_devices
|
||||||
|
|
||||||
|
|
||||||
class DevicesController(RestController):
|
class DevicesController(RestController):
|
||||||
|
|
||||||
usage = UsageController()
|
|
||||||
|
|
||||||
def __init__(self, devid=None):
|
def __init__(self, devid=None):
|
||||||
# Required for PUT requests. See _lookup() below
|
# Required for PUT requests. See _lookup() below
|
||||||
self.devid = devid
|
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 we don't have an id then we want a list of all devices
|
||||||
if not device_id:
|
if not device_id:
|
||||||
# return all devices
|
# return all devices
|
||||||
device = []
|
device = {'devices': []}
|
||||||
|
|
||||||
if marker is None:
|
if marker is None:
|
||||||
marker = 0
|
marker = 0
|
||||||
@@ -85,10 +81,14 @@ class DevicesController(RestController):
|
|||||||
if lbs:
|
if lbs:
|
||||||
for item in lbs:
|
for item in lbs:
|
||||||
lb = item._asdict()
|
lb = item._asdict()
|
||||||
|
lb['hpcs_tenantid'] = lb['tenantid']
|
||||||
|
del(lb['tenantid'])
|
||||||
dev['loadBalancers'].append(lb)
|
dev['loadBalancers'].append(lb)
|
||||||
|
|
||||||
device.append(dev)
|
device['devices'].append(dev)
|
||||||
|
|
||||||
|
elif device_id == 'usage':
|
||||||
|
return self.usage()
|
||||||
else:
|
else:
|
||||||
# return device detail
|
# return device detail
|
||||||
device = session.query(
|
device = session.query(
|
||||||
@@ -128,7 +128,7 @@ class DevicesController(RestController):
|
|||||||
response.status = 200
|
response.status = 200
|
||||||
return device
|
return device
|
||||||
|
|
||||||
@wsme_pecan.wsexpose(DeviceResp, body=DevicePost, status_code=202)
|
@wsme_pecan.wsexpose(DeviceResp, body=DevicePost)
|
||||||
def post(self, body=None):
|
def post(self, body=None):
|
||||||
""" Creates a new device entry in devices table.
|
""" Creates a new device entry in devices table.
|
||||||
:param None
|
:param None
|
||||||
@@ -196,7 +196,7 @@ class DevicesController(RestController):
|
|||||||
session.rollback()
|
session.rollback()
|
||||||
raise ClientSideError(errstr)
|
raise ClientSideError(errstr)
|
||||||
|
|
||||||
@wsme_pecan.wsexpose(None, body=DevicePut, status_code=202)
|
@wsme_pecan.wsexpose(None, body=DevicePut)
|
||||||
def put(self, body=None):
|
def put(self, body=None):
|
||||||
""" Updates a device entry in devices table with new status.
|
""" Updates a device entry in devices table with new status.
|
||||||
Also, updates status of loadbalancers using this device
|
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.query(Device).filter(Device.id == device_id).delete()
|
||||||
session.flush()
|
session.flush()
|
||||||
session.commit()
|
session.commit()
|
||||||
response.status = 202
|
|
||||||
return None
|
return None
|
||||||
except:
|
except:
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -291,6 +290,27 @@ class DevicesController(RestController):
|
|||||||
faultstring="Error deleting device from pool"
|
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')
|
@expose('json')
|
||||||
def _lookup(self, devid, *remainder):
|
def _lookup(self, devid, *remainder):
|
||||||
"""Routes more complex url mapping for PUT
|
"""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):
|
def __init__(self, addresses, logger):
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
|
self.headers = {'Content-type': 'application/json'}
|
||||||
random.shuffle(addresses)
|
random.shuffle(addresses)
|
||||||
for address in addresses:
|
for address in addresses:
|
||||||
self.url = 'https://{0}/{1}'.format(address, API_VERSION)
|
self.url = 'https://{0}/{1}'.format(address, API_VERSION)
|
||||||
@@ -93,7 +94,10 @@ class HPRestDriver(MgmDriver):
|
|||||||
|
|
||||||
def _post(self, url, node_data):
|
def _post(self, url, node_data):
|
||||||
try:
|
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:
|
except requests.exceptions.RequestException:
|
||||||
self.logger.error('Exception communicating to server: {exc}'
|
self.logger.error('Exception communicating to server: {exc}'
|
||||||
.format(exc=sys.exc_info()[0]))
|
.format(exc=sys.exc_info()[0]))
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ class APIError(Exception):
|
|||||||
class AdminAPI(object):
|
class AdminAPI(object):
|
||||||
def __init__(self, addresses, logger):
|
def __init__(self, addresses, logger):
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
|
self.headers = {'Content-type': 'application/json'}
|
||||||
random.shuffle(addresses)
|
random.shuffle(addresses)
|
||||||
for address in addresses:
|
for address in addresses:
|
||||||
self.url = 'https://{0}/v1'.format(address)
|
self.url = 'https://{0}/v1'.format(address)
|
||||||
@@ -113,7 +114,9 @@ class AdminAPI(object):
|
|||||||
|
|
||||||
def _put(self, url, data):
|
def _put(self, url, data):
|
||||||
try:
|
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:
|
except requests.exceptions.RequestException:
|
||||||
self.logger.exception('Exception communicating to server')
|
self.logger.exception('Exception communicating to server')
|
||||||
return False, None
|
return False, None
|
||||||
|
|||||||
Reference in New Issue
Block a user