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
|
# models
|
||||||
from libra.api.model.lbaas import LoadBalancer, Device, Node, session
|
from libra.api.model.lbaas import LoadBalancer, Device, Node, session
|
||||||
from libra.api.model.lbaas import loadbalancers_devices, Limits
|
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.library.gearman_client import submit_job
|
||||||
from libra.api.acl import get_limited_to_project
|
from libra.api.acl import get_limited_to_project
|
||||||
|
|
||||||
|
|
||||||
class LoadBalancersController(RestController):
|
class LoadBalancersController(RestController):
|
||||||
|
def __init__(self, lbid=None):
|
||||||
|
self.lbid = lbid
|
||||||
|
|
||||||
@expose('json')
|
@expose('json')
|
||||||
def get(self, load_balancer_id=None):
|
def get(self, load_balancer_id=None):
|
||||||
"""Fetches a list of load balancers or the details of one balancer if
|
"""Fetches a list of load balancers or the details of one balancer if
|
||||||
@ -116,7 +119,7 @@ class LoadBalancersController(RestController):
|
|||||||
response.status = 200
|
response.status = 200
|
||||||
return load_balancers
|
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):
|
def post(self, body=None):
|
||||||
"""Accepts edit if load_balancer_id isn't blank or create load balancer
|
"""Accepts edit if load_balancer_id isn't blank or create load balancer
|
||||||
posts.
|
posts.
|
||||||
@ -305,6 +308,40 @@ class LoadBalancersController(RestController):
|
|||||||
session.rollback()
|
session.rollback()
|
||||||
raise ClientSideError(errstr)
|
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')
|
@expose('json')
|
||||||
def delete(self, load_balancer_id):
|
def delete(self, load_balancer_id):
|
||||||
"""Remove a load balancer from the account.
|
"""Remove a load balancer from the account.
|
||||||
@ -386,5 +423,7 @@ class LoadBalancersController(RestController):
|
|||||||
return NodesController(lbid), remainder[1:]
|
return NodesController(lbid), remainder[1:]
|
||||||
if remainder[0] == 'virtualips':
|
if remainder[0] == 'virtualips':
|
||||||
return VipsController(lbid), remainder[1:]
|
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)
|
abort(404)
|
||||||
|
@ -13,21 +13,24 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from pecan import expose, response, request
|
from pecan import expose, response, request, 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 wsme import Unset
|
||||||
#default response objects
|
#default response objects
|
||||||
from libra.api.model.lbaas import LoadBalancer, Node, session, Limits, Device
|
from libra.api.model.lbaas import LoadBalancer, Node, session, Limits, Device
|
||||||
from libra.api.acl import get_limited_to_project
|
from libra.api.acl import get_limited_to_project
|
||||||
from libra.api.model.validators import LBNodeResp, LBNodePost, NodeResp
|
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
|
from libra.api.library.gearman_client import submit_job
|
||||||
|
|
||||||
|
|
||||||
class NodesController(RestController):
|
class NodesController(RestController):
|
||||||
"""Functions for /loadbalancers/{load_balancer_id}/nodes/* routing"""
|
"""Functions for /loadbalancers/{load_balancer_id}/nodes/* routing"""
|
||||||
def __init__(self, lbid):
|
def __init__(self, lbid, nodeid=None):
|
||||||
self.lbid = lbid
|
self.lbid = lbid
|
||||||
|
self.nodeid = nodeid
|
||||||
|
|
||||||
@expose('json')
|
@expose('json')
|
||||||
def get(self, node_id=None):
|
def get(self, node_id=None):
|
||||||
@ -89,7 +92,7 @@ class NodesController(RestController):
|
|||||||
response.status = 200
|
response.status = 200
|
||||||
return node_response
|
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):
|
def post(self, body=None):
|
||||||
"""Adds a new node to the load balancer OR Modify the configuration
|
"""Adds a new node to the load balancer OR Modify the configuration
|
||||||
of a node on the load balancer.
|
of a node on the load balancer.
|
||||||
@ -166,6 +169,45 @@ class NodesController(RestController):
|
|||||||
)
|
)
|
||||||
return return_data
|
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')
|
@expose('json')
|
||||||
def delete(self, node_id):
|
def delete(self, node_id):
|
||||||
"""Remove a node from the load balancer.
|
"""Remove a node from the load balancer.
|
||||||
@ -230,3 +272,14 @@ class NodesController(RestController):
|
|||||||
)
|
)
|
||||||
response.status = 202
|
response.status = 202
|
||||||
return None
|
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': [{
|
'loadBalancers': [{
|
||||||
'name': keep_lb.name,
|
'name': keep_lb.name,
|
||||||
'protocol': keep_lb.protocol,
|
'protocol': keep_lb.protocol,
|
||||||
|
'algorithm': keep_lb.algorithm,
|
||||||
'port': keep_lb.port,
|
'port': keep_lb.port,
|
||||||
'nodes': []
|
'nodes': []
|
||||||
}]
|
}]
|
||||||
@ -139,6 +140,7 @@ class GearmanClientThread(object):
|
|||||||
lb_data = {
|
lb_data = {
|
||||||
'name': lb.name,
|
'name': lb.name,
|
||||||
'protocol': lb.protocol,
|
'protocol': lb.protocol,
|
||||||
|
'algorithm': lb.algorithm,
|
||||||
'port': lb.port,
|
'port': lb.port,
|
||||||
'nodes': []
|
'nodes': []
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,17 @@
|
|||||||
|
|
||||||
from wsme import types as wtypes
|
from wsme import types as wtypes
|
||||||
from wsme import wsattr
|
from wsme import wsattr
|
||||||
from wsme.types import Base
|
from wsme.types import Base, Enum
|
||||||
|
|
||||||
|
|
||||||
class LBNode(Base):
|
class LBNode(Base):
|
||||||
port = wsattr(int, mandatory=True)
|
port = wsattr(int, mandatory=True)
|
||||||
address = wsattr(wtypes.text, 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):
|
class NodeResp(Base):
|
||||||
@ -48,11 +52,16 @@ class LBPost(Base):
|
|||||||
name = wsattr(wtypes.text, mandatory=True)
|
name = wsattr(wtypes.text, mandatory=True)
|
||||||
nodes = wsattr(['LBNode'], mandatory=True)
|
nodes = wsattr(['LBNode'], mandatory=True)
|
||||||
protocol = wtypes.text
|
protocol = wtypes.text
|
||||||
algorithm = wtypes.text
|
algorithm = Enum(wtypes.text, 'ROUND_ROBIN', 'LEAST_CONNECTIONS')
|
||||||
port = int
|
port = int
|
||||||
virtualIps = wsattr(['LBVip'])
|
virtualIps = wsattr(['LBVip'])
|
||||||
|
|
||||||
|
|
||||||
|
class LBPut(Base):
|
||||||
|
name = wtypes.text
|
||||||
|
algorithm = Enum(wtypes.text, 'ROUND_ROBIN', 'LEAST_CONNECTIONS')
|
||||||
|
|
||||||
|
|
||||||
class LBVipResp(Base):
|
class LBVipResp(Base):
|
||||||
id = int
|
id = int
|
||||||
address = wtypes.text
|
address = wtypes.text
|
||||||
|
@ -60,7 +60,7 @@ class GearJobs(object):
|
|||||||
list_of_jobs.append(dict(task=str(node), data=job_data))
|
list_of_jobs.append(dict(task=str(node), data=job_data))
|
||||||
submitted_pings = self.gm_client.submit_multiple_jobs(
|
submitted_pings = self.gm_client.submit_multiple_jobs(
|
||||||
list_of_jobs, background=False, wait_until_complete=True,
|
list_of_jobs, background=False, wait_until_complete=True,
|
||||||
poll_timeout=10.0
|
poll_timeout=30.0
|
||||||
)
|
)
|
||||||
for ping in submitted_pings:
|
for ping in submitted_pings:
|
||||||
if ping.state == 'UNKNOWN':
|
if ping.state == 'UNKNOWN':
|
||||||
|
Loading…
x
Reference in New Issue
Block a user