Commit 7e549881 authored by Xavier Thompson's avatar Xavier Thompson

proxy: Forbid several sub-instances with same name

Fix request scope inside instance trees so that an instance is uniquely
identified by its name and the partition of the instance tree's root.

In other words, this allows diamond-shaped instance trees.
parent d7878100
......@@ -29,6 +29,7 @@ CREATE TABLE IF NOT EXISTS partition%(version)s (
software_type VARCHAR(255),
partition_reference VARCHAR(255), -- name of the instance
requested_by VARCHAR(255),
root_partition VARCHAR(255), -- root partition of the instance tree
requested_state VARCHAR(255) NOT NULL DEFAULT 'started',
timestamp REAL,
CONSTRAINT uniq PRIMARY KEY (reference, computer_reference)
......
......@@ -396,6 +396,7 @@ def destroyedComputerPartition():
' software_type=NULL,'
' partition_reference=NULL,'
' requested_by=NULL,'
' root_partition=NULL,'
' requested_state="started"'
'WHERE reference=? AND computer_reference=? ',
[request.form['computer_partition_id'], request.form['computer_id']])
......@@ -527,7 +528,7 @@ def requestComputerPartition():
else:
matching_partition = getAllocatedInstance(
parsed_request_dict['partition_reference'],
parsed_request_dict['partition_id'])
getRootPartitionId(parsed_request_dict['partition_id']))
if matching_partition:
# Then the instance is already allocated, just update it
......@@ -718,14 +719,14 @@ def forwardRequestToExternalMaster(master_url, request_form):
partition._software_release_document = request_form['software_release'] # type: ignore
return dumps(partition)
def getAllocatedInstance(partition_reference, requested_by):
def getAllocatedInstance(partition_reference, root_id):
"""
Look for existence of instance, if so return the
corresponding partition dict, else return None
"""
return execute_db('partition',
'SELECT * FROM %s WHERE partition_reference is ? AND requested_by is ?',
(partition_reference, requested_by or None), one=True)
'SELECT * FROM %s WHERE partition_reference is ? AND root_partition is ?',
(partition_reference, root_id), one=True)
def getAllocatedSlaveInstance(slave_reference, requested_computer_id):
"""
......@@ -740,10 +741,14 @@ def getAllocatedSlaveInstance(slave_reference, requested_computer_id):
'SELECT * FROM %s WHERE reference is ? AND computer_reference is ?',
(slave_reference, requested_computer_id), one=True)
def getPartition(reference):
"""Fetch the partition wth the given reference"""
p = 'SELECT * FROM %s WHERE reference=?'
return execute_db('partition', p, [reference], one=True)
def getRootPartition(reference):
"""Climb the partitions tree up by 'requested_by' link to get the root partition."""
p = 'SELECT * FROM %s WHERE reference=?'
partition = execute_db('partition', p, [reference], one=True)
partition = getPartition(reference)
if partition is None:
app.logger.warning("Nonexisting partition \"{}\". Known are\n{!s}".format(
reference, execute_db("partition", "select reference, requested_by from %s")))
......@@ -753,17 +758,26 @@ def getRootPartition(reference):
requested_by = partition['requested_by']
if requested_by is None or requested_by == reference:
return partition
parent_partition = execute_db('partition', p, (requested_by,), one=True)
parent_partition = getPartition(requested_by)
if parent_partition is None:
return partition
partition = parent_partition
reference = requested_by
def getRootPartitionId(requested_by):
if requested_by:
root = getRootPartition(requested_by)
if root:
return root['reference']
return requested_by
def requestNotSlave(software_release, software_type, partition_reference, partition_id, partition_parameter_kw, filter_kw, requested_state):
instance_xml = dict2xml(partition_parameter_kw)
requested_computer_id = filter_kw['computer_guid']
partition = getAllocatedInstance(partition_reference, partition_id)
root_id = getRootPartitionId(partition_id)
partition = getAllocatedInstance(partition_reference, root_id)
args = []
a = args.append
......@@ -782,11 +796,13 @@ def requestNotSlave(software_release, software_type, partition_reference, partit
if partition_id:
q += ' ,requested_by=?'
a(partition_id)
q += ' ,root_partition=?'
a(root_id)
if not software_type:
software_type = 'RootSoftwareInstance'
else:
if partition['requested_by']:
root_partition = getRootPartition(partition['requested_by'])
root_partition = getPartition(root_id)
if root_partition and root_partition['requested_state'] != "started":
# propagate parent state to child
# child can be stopped or destroyed while parent is started
......
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