Commit 5de858d5 authored by Xavier Thompson's avatar Xavier Thompson

slapproxy: Show shared in slapos service list/info

Improve hateoas support to show shared instances.
parent 9ec07439
......@@ -1037,6 +1037,29 @@ def busy_root_partitions_list(title=None):
partitions.append(p)
return partitions
def busy_root_shared_list(title=None):
shared = []
query = 'SELECT * FROM %s WHERE asked_by==""'
args = []
if title:
query += ' AND reference=?'
args.append('_' + title)
for row in execute_db('slave', query, args):
host = execute_db('partition', 'SELECT * FROM %s WHERE reference=?', [row['hosted_by']], one=True)
if not host:
continue
for slave_dict in loads(host['slave_instance_list'].encode('utf-8')):
if slave_dict['slave_reference'] == row['reference']:
break
else:
continue
s = {}
s['url_string'] = host['software_release']
s['title'] = row['reference'][1:] # root shared are prefixed with _
s['relative_url'] = url_for('hateoas_shared', shared_reference=s['title'])
shared.append(s)
return shared
def computers_list(reference=None):
computers = []
query = 'SELECT * FROM %s'
......@@ -1066,11 +1089,14 @@ p_computer_info = p_computer_list + ' AND reference:='
def parse_query(query):
if query == p_service_list:
return busy_root_partitions_list()
return busy_root_partitions_list() + busy_root_shared_list()
elif query.startswith(p_service_info):
title = query[len(p_service_info):]
if is_valid(title):
return busy_root_partitions_list(title.strip('"'))
partition = busy_root_partitions_list(title.strip('"'))
if partition:
return partition
return busy_root_shared_list(title.strip('"'))
elif query == p_computer_list:
return computers_list()
elif query.startswith(p_computer_info):
......@@ -1084,6 +1110,38 @@ def hateoas_partitions(partition_reference):
partition = execute_db('partition', 'SELECT * FROM %s WHERE partition_reference=?', [partition_reference], one=True)
if partition is None:
abort(404)
partition['reference']=partition['partition_reference']
return hateoas_service_document(**partition, shared=0)
@app.route('/hateoas/shared/<shared_reference>', methods=['GET'])
def hateoas_shared(shared_reference):
slave_reference = '_' + shared_reference # root shared are prefixed with _ in db
shared = execute_db('slave', 'SELECT * FROM %s WHERE reference=?', [slave_reference], one=True)
if shared is None:
abort(404)
partition = execute_db('partition', 'SELECT * FROM %s WHERE reference=?', [shared['hosted_by']], one=True)
if partition is None:
abort(404)
slave_list = loads(partition['slave_instance_list'].encode('utf-8'))
for slave_dict in slave_list:
if slave_dict['slave_reference'] == slave_reference:
break
else:
abort(404)
del slave_dict['slave_title'], slave_dict['slave_reference']
software_type = slave_dict.pop('slap_software_type')
xml = dict2xml(slave_dict)
return hateoas_service_document(
reference = shared_reference,
requested_state='unused',
xml=xml,
connection_xml=shared['connection_xml'],
software_release=partition['software_release'],
software_type=software_type,
shared=1,
)
def hateoas_service_document(**kw):
# my_slap_state corresponds to requested_state, not slap_state.
return {
'_embedded': {
......@@ -1096,37 +1154,37 @@ def hateoas_partitions(partition_reference):
'my_reference': {
'type': 'StringField',
'key': 'field_my_reference',
'default': partition['partition_reference'],
'default': kw['reference'],
},
'my_slap_state': {
'type': 'StringField',
'key': 'field_my_slap_state',
'default': partition['requested_state'],
'default': kw['requested_state'],
},
'my_text_content': {
'type': 'StringField',
'key': 'field_my_text_content',
'default': partition['xml'],
'default': kw['xml'],
},
'my_connection_parameter_list': {
'type': 'StringField',
'key': 'field_my_connection_parameter_list',
'default': partition['connection_xml'],
'default': kw['connection_xml'],
},
'my_url_string': {
'type': 'StringField',
'key': 'field_my_url_string',
'default': partition['software_release'],
'default': kw['software_release'],
},
'my_source_reference': {
'type': 'StringField',
'key': 'field_my_source_reference',
'default': partition['software_type'],
'default': kw['software_type'],
},
'my_root_slave': {
'type': 'IntegerField',
'key': 'field_my_root_slave',
'default': 0,
'default': kw['shared'],
},
},
},
......
......@@ -1289,6 +1289,16 @@ class TestCliInformation(CliMasterMixin):
json.loads(output),
{'MyInstance0': 'http://sr0//', 'MyInstance1': 'http://sr1//', 'MyInstance2': 'http://sr2//'})
def test_service_list_with_shared(self):
self.format_for_number_of_partitions(1)
self.request('http://sr0//', None, 'MyHostInstance0', None)
self.request('http://sr0//', None, 'MySharedInstance1', None, shared=True)
self.request('http://sr0//', None, 'MySharedInstance2', None, shared=True)
output = self.cliDoSlapos(('service', 'list'), stderr=subprocess.DEVNULL)
self.assertEqual(
json.loads(output),
{'MyHostInstance0': 'http://sr0//', 'MySharedInstance1': 'http://sr0//', 'MySharedInstance2': 'http://sr0//'})
def test_service_info(self):
self.format_for_number_of_partitions(3)
self.request('http://sr0//', None, 'MyInstance0', None)
......@@ -1326,6 +1336,38 @@ class TestCliInformation(CliMasterMixin):
except subprocess.CalledProcessError as e:
self.assertIn('Instance MyInstance2 does not exist.', e.output)
def test_service_info_with_shared(self):
self.format_for_number_of_partitions(1)
self.request('http://sr0//', 'MyType1', 'MyHostInstance0', None)
self.request('http://sr0//', 'MyType1', 'MySharedInstance1', None, shared=True, partition_parameter_kw={'couscous': 'hello'})
self.request('http://sr0//', 'MyType1', 'MySharedInstance2', None, shared=True, partition_parameter_kw={'couscous': 'bye'})
output0 = self.cliDoSlapos(('service', 'info', 'MySharedInstance1'), stderr=subprocess.DEVNULL)
self.assertEqual(
json.loads(output0),
{
"software-url": "http://sr0//",
"software-type": "MyType1",
"shared": True,
"requested-state": "unused",
"instance-parameters": {"couscous": "hello"},
"connection-parameters": {},
"status": "unsupported",
},
)
output1 = self.cliDoSlapos(('service', 'info', 'MySharedInstance2'), stderr=subprocess.DEVNULL)
self.assertEqual(
json.loads(output1),
{
"software-url": "http://sr0//",
"software-type": "MyType1",
"shared": True,
"requested-state": "unused",
"instance-parameters": {"couscous": "bye"},
"connection-parameters": {},
"status": "unsupported",
},
)
def test_invalid_service_names(self):
invalid_names = ('"MyInstance0', 'MyInstance1"', 'My"Instance2', 'title:="MyInstance3"', 'reference:="MyInstance4"')
self.format_for_number_of_partitions(len(invalid_names))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment