Commit a3be5ed0 authored by Cédric Le Ninivin's avatar Cédric Le Ninivin Committed by Titouan Soulard

slapconfiguration: Use local instance file when available

* Also store shared instance list after retrieving it
parent 12b7ff95
...@@ -36,6 +36,7 @@ import six ...@@ -36,6 +36,7 @@ import six
from six.moves.configparser import RawConfigParser from six.moves.configparser import RawConfigParser
from netaddr import valid_ipv4, valid_ipv6 from netaddr import valid_ipv4, valid_ipv6
from slapos.util import mkdir_p, dumps, calculate_dict_hash from slapos.util import mkdir_p, dumps, calculate_dict_hash
from slapos.grid.SlapObject import SOFTWARE_INSTANCE_JSON_FILENAME
from slapos import format as slapformat from slapos import format as slapformat
...@@ -134,24 +135,35 @@ class Recipe(object): ...@@ -134,24 +135,35 @@ class Recipe(object):
1. SlapOS Master - for external computer/partition information 1. SlapOS Master - for external computer/partition information
2. format.Partition.resource_file - for partition specific details 2. format.Partition.resource_file - for partition specific details
""" """
software_instance = None
instance_json_path = os.path.join(instance_root, SOFTWARE_INSTANCE_JSON_FILENAME)
if os.path.exists(instance_json_path):
with open(instance_json_path, "r") as f:
software_instance = json.load(f)
slap = slapos.slap.slap() slap = slapos.slap.slap()
slap.initializeConnection( slap.initializeConnection(
options['url'], options['url'],
options.get('key'), options.get('key'),
options.get('cert'), options.get('cert'),
) )
if slap.jio_api_connector:
if options.get("software-instance-reference"): # Fallback to requesting to SlapOS Master
software_instance = slap.jio_api_connector.get({ if not software_instance:
"portal_type": "Software Instance", if slap.jio_api_connector:
"reference": options.get("software-instance-reference"), if options.get("software-instance-reference"):
}) software_instance = slap.jio_api_connector.get({
else: "portal_type": "Software Instance",
software_instance = slap.jio_api_connector.get({ "reference": options.get("software-instance-reference"),
"portal_type": "Software Instance", })
"compute_node_id": options["computer"], else:
"compute_partition_id": options["partition"], software_instance = slap.jio_api_connector.get({
}) "portal_type": "Software Instance",
"compute_node_id": options["computer"],
"compute_partition_id": options["partition"],
})
if software_instance:
options["instance-state"] = software_instance.get("state") options["instance-state"] = software_instance.get("state")
options["slap-software-type"] = software_instance.get("software_type") options["slap-software-type"] = software_instance.get("software_type")
options["slap-computer-partition-id"] = software_instance.get("compute_partition_id") options["slap-computer-partition-id"] = software_instance.get("compute_partition_id")
...@@ -166,33 +178,43 @@ class Recipe(object): ...@@ -166,33 +178,43 @@ class Recipe(object):
parameter_dict = json_loads_byteified(software_instance.get("parameters")) parameter_dict = json_loads_byteified(software_instance.get("parameters"))
# Get Share instance list # Get Share instance list
result_shared_instance_list = slap.jio_api_connector.allDocs({ if not "slave_instance_list" in software_instance:
"portal_type": "Shared Instance", result_shared_instance_list = slap.jio_api_connector.allDocs({
"host_instance_reference": software_instance.get("reference"), "portal_type": "Shared Instance",
"state": "started", "host_instance_reference": software_instance.get("reference"),
}).get("result_list", []) "state": "started",
shared_instance_list = [] }).get("result_list", [])
for shared_instance_brain in result_shared_instance_list: shared_instance_list = []
shared_instance = slap.jio_api_connector.get({ for shared_instance_brain in result_shared_instance_list:
"portal_type": "Software Instance", shared_instance = slap.jio_api_connector.get({
"reference": shared_instance_brain.get("reference"), "portal_type": "Software Instance",
}) "reference": shared_instance_brain.get("reference"),
shared_instance_parameter = json_loads_byteified(shared_instance.get("parameters")) })
shared_instance_connection = shared_instance.get("connection_parameters") shared_instance_parameter = json_loads_byteified(shared_instance.get("parameters"))
shared_instance_list.append({ shared_instance_connection = shared_instance.get("connection_parameters")
'slave_title': shared_instance.get("title"), shared_instance_list.append({
'slap_software_type': \ 'slave_title': shared_instance.get("title"),
shared_instance.get("software_type"), 'slap_software_type': \
'slave_reference': shared_instance.get("reference"), shared_instance.get("software_type"),
'timestamp': shared_instance.get("processing_timestamp"), 'slave_reference': shared_instance.get("reference"),
'xml': dumps(shared_instance_parameter), 'timestamp': shared_instance.get("processing_timestamp"),
'parameters': shared_instance_parameter, 'xml': dumps(shared_instance_parameter),
'connection_xml': dumps(shared_instance_connection), 'parameters': shared_instance_parameter,
'connection_parameters': shared_instance_connection, 'connection_xml': dumps(shared_instance_connection),
'connection-parameter-hash': calculate_dict_hash(shared_instance_connection), 'connection_parameters': shared_instance_connection,
}) 'connection-parameter-hash': calculate_dict_hash(shared_instance_connection),
options["slave-instance-list"] = shared_instance_list })
options["shared-instance-list"] = shared_instance_list # XXX CLN Should we update the content of software instance json with shared instance list
else:
shared_instance_list = software_instance["slave_instance_list"]
options["slave-instance-list"] = shared_instance_list
options["shared-instance-list"] = shared_instance_list
if not "slave_instance_list" in software_instance:
software_instance["slave_instance_list"] = shared_instance_list
with open(instance_json_path, "w") as f:
software_instance = json.dump(software_instance, f, indent=2)
else: else:
computer_partition = slap.registerComputerPartition( computer_partition = slap.registerComputerPartition(
options['computer'], options['computer'],
...@@ -274,7 +296,7 @@ class Recipe(object): ...@@ -274,7 +296,7 @@ class Recipe(object):
if storage_home and os.path.exists(storage_home) and \ if storage_home and os.path.exists(storage_home) and \
os.path.isdir(storage_home): os.path.isdir(storage_home):
for filename in os.listdir(storage_home): for filename in os.listdir(storage_home):
storage_path = os.path.join(storage_home, filename, storage_path = os.path.join(storage_home, filename,
options['slap-computer-partition-id']) options['slap-computer-partition-id'])
if os.path.exists(storage_path) and os.path.isdir(storage_path): if os.path.exists(storage_path) and os.path.isdir(storage_path):
storage_link = os.path.join(instance_root, 'DATA', filename) storage_link = os.path.join(instance_root, 'DATA', filename)
......
...@@ -8,6 +8,7 @@ import tempfile ...@@ -8,6 +8,7 @@ import tempfile
from collections import defaultdict from collections import defaultdict
from slapos.recipe import slapconfiguration from slapos.recipe import slapconfiguration
from slapos import format as slapformat from slapos import format as slapformat
from slapos.grid.SlapObject import SOFTWARE_INSTANCE_JSON_FILENAME
from slapos.util import dumps, calculate_dict_hash from slapos.util import dumps, calculate_dict_hash
...@@ -32,7 +33,7 @@ class APIRequestHandler(object): ...@@ -32,7 +33,7 @@ class APIRequestHandler(object):
return self.response_list.pop(0)[1] return self.response_list.pop(0)[1]
class SlapConfigurationTest(unittest.TestCase): class SlapConfigurationTestMixin(object):
def setUp(self): def setUp(self):
"""Prepare files on filesystem.""" """Prepare files on filesystem."""
...@@ -49,6 +50,10 @@ class SlapConfigurationTest(unittest.TestCase): ...@@ -49,6 +50,10 @@ class SlapConfigurationTest(unittest.TestCase):
} }
with open(self.resource_file, "wt") as fo: with open(self.resource_file, "wt") as fo:
json.dump(self.resource, fo) json.dump(self.resource, fo)
self.instance_json_location = os.path.join(
self.instance_root,
SOFTWARE_INSTANCE_JSON_FILENAME
)
# do your tests inside try block and clean up in finally # do your tests inside try block and clean up in finally
self.buildout = { self.buildout = {
"buildout": { "buildout": {
...@@ -58,9 +63,11 @@ class SlapConfigurationTest(unittest.TestCase): ...@@ -58,9 +63,11 @@ class SlapConfigurationTest(unittest.TestCase):
def tearDown(self): def tearDown(self):
os.unlink(self.resource_file) os.unlink(self.resource_file)
if os.path.exists(self.instance_json_location):
os.unlink(self.instance_json_location)
os.rmdir(self.instance_root) os.rmdir(self.instance_root)
def test_new_api(self): def test_no_shared_instance(self):
"""Test proper call with new api""" """Test proper call with new api"""
options = { options = {
...@@ -91,10 +98,17 @@ class SlapConfigurationTest(unittest.TestCase): ...@@ -91,10 +98,17 @@ class SlapConfigurationTest(unittest.TestCase):
"parameters": json.dumps(parameter_dict), "parameters": json.dumps(parameter_dict),
"connection_parameters": {"1": 2, "3": "YourURL"}, "connection_parameters": {"1": 2, "3": "YourURL"},
} }
api_handler = APIRequestHandler([ if self.use_api:
("/api/get", json.dumps(instance_data)), api_handler = APIRequestHandler([
("/api/allDocs", json.dumps({"result_list": []})) ("/api/get", json.dumps(instance_data)),
]) ("/api/allDocs", json.dumps({"result_list": []}))
])
else:
with open(self.instance_json_location, 'w') as f:
json.dump(instance_data, f, indent=2)
api_handler = APIRequestHandler([
("/api/allDocs", json.dumps({"result_list": []}))
])
with httmock.HTTMock(api_handler.request_handler): with httmock.HTTMock(api_handler.request_handler):
slapconfiguration.Recipe(self.buildout, "slapconfiguration", options) slapconfiguration.Recipe(self.buildout, "slapconfiguration", options)
...@@ -119,7 +133,7 @@ class SlapConfigurationTest(unittest.TestCase): ...@@ -119,7 +133,7 @@ class SlapConfigurationTest(unittest.TestCase):
self.assertEqual(options['address-list'], [10, 20], self.assertEqual(options['address-list'], [10, 20],
"All underscores should be replaced with -") "All underscores should be replaced with -")
def test_new_api_with_shared_instance(self): def test_with_shared_instance(self):
"""Test proper call with new api""" """Test proper call with new api"""
options = { options = {
...@@ -174,14 +188,25 @@ class SlapConfigurationTest(unittest.TestCase): ...@@ -174,14 +188,25 @@ class SlapConfigurationTest(unittest.TestCase):
"parameters": json.dumps(shared_instance_parameter_dict), "parameters": json.dumps(shared_instance_parameter_dict),
"connection_parameters": {"4": 6, "8": "YourURL2"}, "connection_parameters": {"4": 6, "8": "YourURL2"},
} }
api_handler = APIRequestHandler([ if self.use_api:
("/api/get", json.dumps(instance_data)), api_handler = APIRequestHandler([
("/api/allDocs", json.dumps({"result_list": [{ ("/api/get", json.dumps(instance_data)),
"portal_type": "Shared Instance", ("/api/allDocs", json.dumps({"result_list": [{
"reference": shared_instance_data["reference"] "portal_type": "Shared Instance",
}]})), "reference": shared_instance_data["reference"]
("/api/get", json.dumps(shared_instance_data)), }]})),
]) ("/api/get", json.dumps(shared_instance_data)),
])
else:
with open(self.instance_json_location, 'w') as f:
json.dump(instance_data, f, indent=2)
api_handler = APIRequestHandler([
("/api/allDocs", json.dumps({"result_list": [{
"portal_type": "Shared Instance",
"reference": shared_instance_data["reference"]
}]})),
("/api/get", json.dumps(shared_instance_data)),
])
with httmock.HTTMock(api_handler.request_handler): with httmock.HTTMock(api_handler.request_handler):
slapconfiguration.Recipe(self.buildout, "slapconfiguration", options) slapconfiguration.Recipe(self.buildout, "slapconfiguration", options)
...@@ -213,4 +238,15 @@ class SlapConfigurationTest(unittest.TestCase): ...@@ -213,4 +238,15 @@ class SlapConfigurationTest(unittest.TestCase):
'connection_parameters': shared_instance_data.get("connection_parameters"), 'connection_parameters': shared_instance_data.get("connection_parameters"),
'connection-parameter-hash': calculate_dict_hash(shared_instance_data.get("connection_parameters")), 'connection-parameter-hash': calculate_dict_hash(shared_instance_data.get("connection_parameters")),
} }
]) ])
\ No newline at end of file
if not self.use_api:
with open(self.instance_json_location, "r") as f:
dumped_data = json.load(f)
self.assertEqual(dumped_data["slave_instance_list"], options["shared-instance-list"])
class SlapConfigurationWithLocalInstanceFile(SlapConfigurationTestMixin, unittest.TestCase):
use_api = True
class SlapConfigurationWithApi(SlapConfigurationTestMixin, unittest.TestCase):
use_api = False
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