Charmhelper sync
This commit is contained in:
parent
c0904504b1
commit
a95691cd73
@ -414,10 +414,16 @@ class CephBrokerRq(object):
|
|||||||
|
|
||||||
The API is versioned and defaults to version 1.
|
The API is versioned and defaults to version 1.
|
||||||
"""
|
"""
|
||||||
def __init__(self, api_version=1):
|
def __init__(self, api_version=1, ops=None, request_id=None):
|
||||||
self.api_version = api_version
|
self.api_version = api_version
|
||||||
self.request_id = str(uuid.uuid1())
|
if request_id:
|
||||||
self.ops = []
|
self.request_id = request_id
|
||||||
|
else:
|
||||||
|
self.request_id = str(uuid.uuid1())
|
||||||
|
if ops:
|
||||||
|
self.ops = ops
|
||||||
|
else:
|
||||||
|
self.ops = []
|
||||||
|
|
||||||
def add_op_create_pool(self, name, replica_count=3):
|
def add_op_create_pool(self, name, replica_count=3):
|
||||||
self.ops.append({'op': 'create-pool', 'name': name,
|
self.ops.append({'op': 'create-pool', 'name': name,
|
||||||
@ -428,6 +434,28 @@ class CephBrokerRq(object):
|
|||||||
return json.dumps({'api-version': self.api_version, 'ops': self.ops,
|
return json.dumps({'api-version': self.api_version, 'ops': self.ops,
|
||||||
'request-id': self.request_id})
|
'request-id': self.request_id})
|
||||||
|
|
||||||
|
def _ops_equal(self, other):
|
||||||
|
if len(self.ops) == len(other.ops):
|
||||||
|
for req_no in range(0, len(self.ops)):
|
||||||
|
for key in ['replicas', 'name', 'op']:
|
||||||
|
if self.ops[req_no][key] != other.ops[req_no][key]:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if not isinstance(other, self.__class__):
|
||||||
|
return False
|
||||||
|
if self.api_version == other.api_version and \
|
||||||
|
self._ops_equal(other):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def __ne__(self, other):
|
||||||
|
return not self.__eq__(other)
|
||||||
|
|
||||||
|
|
||||||
class CephBrokerRsp(object):
|
class CephBrokerRsp(object):
|
||||||
"""Ceph broker response.
|
"""Ceph broker response.
|
||||||
@ -454,17 +482,42 @@ class CephBrokerRsp(object):
|
|||||||
return self.rsp.get('stderr')
|
return self.rsp.get('stderr')
|
||||||
|
|
||||||
|
|
||||||
def request_states(request_needed):
|
def get_previous_request(rid):
|
||||||
"""Return dict showing if a request has been sent and completed per rid"""
|
"""Return the last ceph broker request sent on a given relation
|
||||||
|
|
||||||
|
@param rid: Relation id to query for request
|
||||||
|
"""
|
||||||
|
request = None
|
||||||
|
broker_req = relation_get(attribute='broker_req', rid=rid,
|
||||||
|
unit=local_unit())
|
||||||
|
if broker_req:
|
||||||
|
request_data = json.loads(broker_req)
|
||||||
|
request = CephBrokerRq(api_version=request_data['api-version'],
|
||||||
|
ops=request_data['ops'],
|
||||||
|
request_id=request_data['request-id'])
|
||||||
|
return request
|
||||||
|
|
||||||
|
|
||||||
|
def get_request_states(request):
|
||||||
|
"""Return a dict of requests per relation id with their corresponding
|
||||||
|
completion state.
|
||||||
|
|
||||||
|
This allows a charm, which has a request for ceph, to see whether there is
|
||||||
|
an equivalent request already being processed and if so what state that
|
||||||
|
request is in.
|
||||||
|
|
||||||
|
@param request: A CephBrokerRq object
|
||||||
|
"""
|
||||||
complete = []
|
complete = []
|
||||||
requests = {}
|
requests = {}
|
||||||
for rid in relation_ids('ceph'):
|
for rid in relation_ids('ceph'):
|
||||||
complete = False
|
complete = False
|
||||||
previous_request = relation_get(attribute='broker_req', rid=rid, unit=local_unit())
|
previous_request = get_previous_request(rid)
|
||||||
sent = equivalent_broker_requests(previous_request, request_needed.request)
|
if request == previous_request:
|
||||||
if sent:
|
sent = True
|
||||||
complete = broker_request_completed(previous_request, rid)
|
complete = is_broker_request_complete(previous_request, rid)
|
||||||
else:
|
else:
|
||||||
|
sent = False
|
||||||
complete = False
|
complete = False
|
||||||
requests[rid] = {
|
requests[rid] = {
|
||||||
'sent': sent,
|
'sent': sent,
|
||||||
@ -473,48 +526,47 @@ def request_states(request_needed):
|
|||||||
return requests
|
return requests
|
||||||
|
|
||||||
|
|
||||||
def request_sent(request_needed):
|
def is_request_sent(request):
|
||||||
"""Check to see if a matching request has been sent"""
|
"""Check to see if a functionally equivalent request has already been sent
|
||||||
states = request_states(request_needed)
|
|
||||||
|
Returns True if a similair request has been sent
|
||||||
|
|
||||||
|
@param request: A CephBrokerRq object
|
||||||
|
"""
|
||||||
|
states = get_request_states(request)
|
||||||
for rid in states.keys():
|
for rid in states.keys():
|
||||||
if not states[rid]['sent']:
|
if not states[rid]['sent']:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def request_complete(request_needed):
|
def is_request_complete(request):
|
||||||
"""Check to see if a matching request has been completed"""
|
"""Check to see if a functionally equivalent request has already been
|
||||||
states = request_states(request_needed)
|
completed
|
||||||
|
|
||||||
|
Returns True if a similair request has been completed
|
||||||
|
|
||||||
|
@param request: A CephBrokerRq object
|
||||||
|
"""
|
||||||
|
states = get_request_states(request)
|
||||||
for rid in states.keys():
|
for rid in states.keys():
|
||||||
if not states[rid]['complete']:
|
if not states[rid]['complete']:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def equivalent_broker_requests(encoded_req1, encoded_req2):
|
def is_broker_request_complete(request, rid):
|
||||||
"""Check to see if two requests are equivalent (ignore request id)"""
|
"""Check if a given request has been completed on the given relation
|
||||||
if not encoded_req1 or not encoded_req2:
|
|
||||||
return False
|
|
||||||
req1 = json.loads(encoded_req1)
|
|
||||||
req2 = json.loads(encoded_req2)
|
|
||||||
if len(req1['ops']) != len(req2['ops']):
|
|
||||||
return False
|
|
||||||
for req_no in range(0, len(req1['ops'])):
|
|
||||||
for key in ['replicas', 'name', 'op']:
|
|
||||||
if req1['ops'][req_no][key] != req2['ops'][req_no][key]:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
@param request: A CephBrokerRq object
|
||||||
def broker_request_completed(encoded_req, rid):
|
@param rid: Relation ID
|
||||||
"""Check if a given request has been completed on the given relation"""
|
"""
|
||||||
req = json.loads(encoded_req)
|
|
||||||
broker_key = get_broker_rsp_key()
|
broker_key = get_broker_rsp_key()
|
||||||
for unit in related_units(rid):
|
for unit in related_units(rid):
|
||||||
rdata = relation_get(rid=rid, unit=unit)
|
rdata = relation_get(rid=rid, unit=unit)
|
||||||
if rdata.get(broker_key):
|
if rdata.get(broker_key):
|
||||||
rsp = CephBrokerRsp(rdata.get(broker_key))
|
rsp = CephBrokerRsp(rdata.get(broker_key))
|
||||||
if rsp.request_id == req.get('request-id'):
|
if rsp.request_id == request.request_id:
|
||||||
if not rsp.exit_code:
|
if not rsp.exit_code:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
@ -522,12 +574,13 @@ def broker_request_completed(encoded_req, rid):
|
|||||||
# remote ceph cluster does not support unit targeted replies or it
|
# remote ceph cluster does not support unit targeted replies or it
|
||||||
# has not processed our request yet.
|
# has not processed our request yet.
|
||||||
if rdata.get('broker_rsp'):
|
if rdata.get('broker_rsp'):
|
||||||
if rdata.get('unit-targeted-reponses'):
|
request_data = json.loads(rdata['broker_rsp'])
|
||||||
|
if request_data.get('request-id'):
|
||||||
log('Ignoring legacy broker_rsp without unit key as remote '
|
log('Ignoring legacy broker_rsp without unit key as remote '
|
||||||
'service supports unit specific replies')
|
'service supports unit specific replies', level=DEBUG)
|
||||||
else:
|
else:
|
||||||
log('Using legacy broker_rsp as remote service does not '
|
log('Using legacy broker_rsp as remote service does not '
|
||||||
'supports unit specific replies')
|
'supports unit specific replies', level=DEBUG)
|
||||||
rsp = CephBrokerRsp(rdata['broker_rsp'])
|
rsp = CephBrokerRsp(rdata['broker_rsp'])
|
||||||
if not rsp.exit_code:
|
if not rsp.exit_code:
|
||||||
return True
|
return True
|
||||||
@ -535,15 +588,23 @@ def broker_request_completed(encoded_req, rid):
|
|||||||
|
|
||||||
|
|
||||||
def get_broker_rsp_key():
|
def get_broker_rsp_key():
|
||||||
"""Return broker request key for this unit"""
|
"""Return broker response key for this unit
|
||||||
|
|
||||||
|
This is the key that ceph is going to use to pass request status
|
||||||
|
information back to this unit
|
||||||
|
"""
|
||||||
return 'broker-rsp-' + local_unit().replace('/', '-')
|
return 'broker-rsp-' + local_unit().replace('/', '-')
|
||||||
|
|
||||||
|
|
||||||
def send_request_if_needed(rq):
|
def send_request_if_needed(request):
|
||||||
"""Send broker request if one has not already been sent"""
|
"""Send broker request if an equivalent request has not already been sent
|
||||||
if request_sent(rq):
|
|
||||||
log('Request already sent but not complete, not sending new request')
|
@param request: A CephBrokerRq object
|
||||||
|
"""
|
||||||
|
if is_request_sent(request):
|
||||||
|
log('Request already sent but not complete, not sending new request',
|
||||||
|
level=DEBUG)
|
||||||
else:
|
else:
|
||||||
for rid in relation_ids('ceph'):
|
for rid in relation_ids('ceph'):
|
||||||
log('Sending request {}'.format(rq.request_id))
|
log('Sending request {}'.format(request.request_id), level=DEBUG)
|
||||||
relation_set(relation_id=rid, broker_req=rq.request)
|
relation_set(relation_id=rid, broker_req=request.request)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user