API+STATSD: Fixes
Statsd: * Increase retry timeout to 30 seconds to work around weird worker pause API: * Add modify and node-modify support (and kludge to wsme to make it work) * Fix status codes for wsme (currently requires trunk version of wsme) Change-Id: Ib5f30b0d6306c4105fd30a6ca588a89ba96d29ee
This commit is contained in:
parent
e7657309da
commit
b8e7a919ba
@ -25,12 +25,15 @@ from virtualips import VipsController
|
||||
# models
|
||||
from libra.api.model.lbaas import LoadBalancer, Device, Node, session
|
||||
from libra.api.model.lbaas import loadbalancers_devices, Limits
|
||||
from libra.api.model.validators import LBPost, LBResp, LBVipResp, LBNode
|
||||
from libra.api.model.validators import LBPut, LBPost, LBResp, LBVipResp, LBNode
|
||||
from libra.api.library.gearman_client import submit_job
|
||||
from libra.api.acl import get_limited_to_project
|
||||
|
||||
|
||||
class LoadBalancersController(RestController):
|
||||
def __init__(self, lbid=None):
|
||||
self.lbid = lbid
|
||||
|
||||
@expose('json')
|
||||
def get(self, load_balancer_id=None):
|
||||
"""Fetches a list of load balancers or the details of one balancer if
|
||||
@ -116,7 +119,7 @@ class LoadBalancersController(RestController):
|
||||
response.status = 200
|
||||
return load_balancers
|
||||
|
||||
@wsme_pecan.wsexpose(LBResp, body=LBPost, status=202)
|
||||
@wsme_pecan.wsexpose(LBResp, body=LBPost, status_code=202)
|
||||
def post(self, body=None):
|
||||
"""Accepts edit if load_balancer_id isn't blank or create load balancer
|
||||
posts.
|
||||
@ -305,6 +308,40 @@ class LoadBalancersController(RestController):
|
||||
session.rollback()
|
||||
raise ClientSideError(errstr)
|
||||
|
||||
@wsme_pecan.wsexpose(None, body=LBPut, status_code=202)
|
||||
def put(self, body=None):
|
||||
if not self.lbid:
|
||||
raise ClientSideError('Load Balancer ID is required')
|
||||
|
||||
tenant_id = get_limited_to_project(request.headers)
|
||||
|
||||
# grab the lb
|
||||
lb = session.query(LoadBalancer).\
|
||||
filter(LoadBalancer.id == self.lbid).\
|
||||
filter(LoadBalancer.tenantid == tenant_id).\
|
||||
filter(LoadBalancer.status != 'DELETED').first()
|
||||
|
||||
if lb is None:
|
||||
raise ClientSideError('Load Balancer ID is not valid')
|
||||
|
||||
if body.name != Unset:
|
||||
lb.name = body.name
|
||||
|
||||
if body.algorithm != Unset:
|
||||
lb.algorithm = body.algorithm
|
||||
|
||||
lb.status = 'PENDING_UPDATE'
|
||||
device = session.query(
|
||||
Device.id, Device.name
|
||||
).join(LoadBalancer.devices).\
|
||||
filter(LoadBalancer.id == self.lbid).\
|
||||
first()
|
||||
session.commit()
|
||||
submit_job(
|
||||
'UPDATE', device.name, device.id, lb.id
|
||||
)
|
||||
return
|
||||
|
||||
@expose('json')
|
||||
def delete(self, load_balancer_id):
|
||||
"""Remove a load balancer from the account.
|
||||
@ -386,5 +423,7 @@ class LoadBalancersController(RestController):
|
||||
return NodesController(lbid), remainder[1:]
|
||||
if remainder[0] == 'virtualips':
|
||||
return VipsController(lbid), remainder[1:]
|
||||
|
||||
# Kludgy fix for PUT since WSME doesn't like IDs on the path
|
||||
elif lbid:
|
||||
return LoadBalancersController(lbid), remainder
|
||||
abort(404)
|
||||
|
@ -13,21 +13,24 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from pecan import expose, response, request
|
||||
from pecan import expose, response, request, abort
|
||||
from pecan.rest import RestController
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
from wsme.exc import ClientSideError
|
||||
from wsme import Unset
|
||||
#default response objects
|
||||
from libra.api.model.lbaas import LoadBalancer, Node, session, Limits, Device
|
||||
from libra.api.acl import get_limited_to_project
|
||||
from libra.api.model.validators import LBNodeResp, LBNodePost, NodeResp
|
||||
from libra.api.model.validators import LBNodePut
|
||||
from libra.api.library.gearman_client import submit_job
|
||||
|
||||
|
||||
class NodesController(RestController):
|
||||
"""Functions for /loadbalancers/{load_balancer_id}/nodes/* routing"""
|
||||
def __init__(self, lbid):
|
||||
def __init__(self, lbid, nodeid=None):
|
||||
self.lbid = lbid
|
||||
self.nodeid = nodeid
|
||||
|
||||
@expose('json')
|
||||
def get(self, node_id=None):
|
||||
@ -89,7 +92,7 @@ class NodesController(RestController):
|
||||
response.status = 200
|
||||
return node_response
|
||||
|
||||
@wsme_pecan.wsexpose(LBNodeResp, body=LBNodePost, status=202)
|
||||
@wsme_pecan.wsexpose(LBNodeResp, body=LBNodePost, status_code=202)
|
||||
def post(self, body=None):
|
||||
"""Adds a new node to the load balancer OR Modify the configuration
|
||||
of a node on the load balancer.
|
||||
@ -166,6 +169,45 @@ class NodesController(RestController):
|
||||
)
|
||||
return return_data
|
||||
|
||||
@wsme_pecan.wsexpose(None, body=LBNodePut, status_code=202)
|
||||
def put(self, body=None):
|
||||
if not self.lbid:
|
||||
raise ClientSideError('Load Balancer ID has not been supplied')
|
||||
if not self.nodeid:
|
||||
raise ClientSideError('Node ID has not been supplied')
|
||||
|
||||
tenant_id = get_limited_to_project(request.headers)
|
||||
# grab the lb
|
||||
lb = session.query(LoadBalancer).\
|
||||
filter(LoadBalancer.id == self.lbid).\
|
||||
filter(LoadBalancer.tenantid == tenant_id).\
|
||||
filter(LoadBalancer.status != 'DELETED').first()
|
||||
|
||||
if lb is None:
|
||||
raise ClientSideError('Load Balancer ID is not valid')
|
||||
|
||||
node = session.query(Node).\
|
||||
filter(Node.lbid == self.lbid).\
|
||||
filter(Node.id == self.nodeid).first()
|
||||
|
||||
if node is None:
|
||||
raise ClientSideError('Node ID is not valid')
|
||||
|
||||
if body.condition != Unset:
|
||||
node.condition = body.condition
|
||||
|
||||
lb.status = 'PENDING_UPDATE'
|
||||
device = session.query(
|
||||
Device.id, Device.name
|
||||
).join(LoadBalancer.devices).\
|
||||
filter(LoadBalancer.id == self.lbid).\
|
||||
first()
|
||||
session.commit()
|
||||
submit_job(
|
||||
'UPDATE', device.name, device.id, lb.id
|
||||
)
|
||||
return
|
||||
|
||||
@expose('json')
|
||||
def delete(self, node_id):
|
||||
"""Remove a node from the load balancer.
|
||||
@ -230,3 +272,14 @@ class NodesController(RestController):
|
||||
)
|
||||
response.status = 202
|
||||
return None
|
||||
|
||||
@expose('json')
|
||||
def _lookup(self, nodeid, *remainder):
|
||||
"""Routes more complex url mapping.
|
||||
|
||||
Raises: 404
|
||||
"""
|
||||
# Kludgy fix for PUT since WSME doesn't like IDs on the path
|
||||
if nodeid:
|
||||
return NodesController(self.lbid, nodeid), remainder
|
||||
abort(404)
|
||||
|
@ -74,6 +74,7 @@ class GearmanClientThread(object):
|
||||
'loadBalancers': [{
|
||||
'name': keep_lb.name,
|
||||
'protocol': keep_lb.protocol,
|
||||
'algorithm': keep_lb.algorithm,
|
||||
'port': keep_lb.port,
|
||||
'nodes': []
|
||||
}]
|
||||
@ -139,6 +140,7 @@ class GearmanClientThread(object):
|
||||
lb_data = {
|
||||
'name': lb.name,
|
||||
'protocol': lb.protocol,
|
||||
'algorithm': lb.algorithm,
|
||||
'port': lb.port,
|
||||
'nodes': []
|
||||
}
|
||||
|
@ -15,13 +15,17 @@
|
||||
|
||||
from wsme import types as wtypes
|
||||
from wsme import wsattr
|
||||
from wsme.types import Base
|
||||
from wsme.types import Base, Enum
|
||||
|
||||
|
||||
class LBNode(Base):
|
||||
port = wsattr(int, mandatory=True)
|
||||
address = wsattr(wtypes.text, mandatory=True)
|
||||
condition = wtypes.text
|
||||
condition = Enum(wtypes.text, 'ENABLED', 'DISABLED')
|
||||
|
||||
|
||||
class LBNodePut(Base):
|
||||
condition = Enum(wtypes.text, 'ENABLED', 'DISABLED')
|
||||
|
||||
|
||||
class NodeResp(Base):
|
||||
@ -48,11 +52,16 @@ class LBPost(Base):
|
||||
name = wsattr(wtypes.text, mandatory=True)
|
||||
nodes = wsattr(['LBNode'], mandatory=True)
|
||||
protocol = wtypes.text
|
||||
algorithm = wtypes.text
|
||||
algorithm = Enum(wtypes.text, 'ROUND_ROBIN', 'LEAST_CONNECTIONS')
|
||||
port = int
|
||||
virtualIps = wsattr(['LBVip'])
|
||||
|
||||
|
||||
class LBPut(Base):
|
||||
name = wtypes.text
|
||||
algorithm = Enum(wtypes.text, 'ROUND_ROBIN', 'LEAST_CONNECTIONS')
|
||||
|
||||
|
||||
class LBVipResp(Base):
|
||||
id = int
|
||||
address = wtypes.text
|
||||
|
@ -60,7 +60,7 @@ class GearJobs(object):
|
||||
list_of_jobs.append(dict(task=str(node), data=job_data))
|
||||
submitted_pings = self.gm_client.submit_multiple_jobs(
|
||||
list_of_jobs, background=False, wait_until_complete=True,
|
||||
poll_timeout=10.0
|
||||
poll_timeout=30.0
|
||||
)
|
||||
for ping in submitted_pings:
|
||||
if ping.state == 'UNKNOWN':
|
||||
|
Loading…
x
Reference in New Issue
Block a user