Commit 24a4ed2b authored by Romain Courteaud's avatar Romain Courteaud

Reduce and simplify catalog queries.

SlapOS master does not decide anymore if the client has to run buildout or not.
This has to be done on client side.

Use information filled in request to find newly created documents.

Fix slave partition request and return correct informations.
parent f72b71c9
......@@ -492,26 +492,39 @@ class SlapTool(BaseTool):
slap_partition._requested_state = 'destroyed'
slap_partition._need_modification = 0
if computer_partition_document.getSlapState() != 'busy':
update_movement = None
movement = None
else:
update_movement = self._getSalePackingListLineForComputerPartition(
computer_partition_document, service_uid_list=[portal.restrictedTraverse(portal_preferences.getPreferredInstanceUpdateResource()).getUid()])
movement = self._getSalePackingListLineForComputerPartition(
computer_partition_document)
if update_movement is not None:
if update_movement.getSimulationState() != 'confirmed':
# only confirmed update movements are interesting
update_movement = None
if movement is not None:
software_release_document = \
movement.getAggregateValue(portal_type='Software Release')
slap_partition._software_release_document = SoftwareRelease(
software_release=software_release_document.getUrlString(),
software_instance = None
if computer_partition_document.getSlapState() == 'busy':
software_instance_list = portal.portal_catalog(
portal_type="Software Instance",
default_aggregate_uid=computer_partition_document.getUid(),
validation_state="validated",
limit=2,
)
software_instance_count = len(software_instance_list)
if software_instance_count == 1:
software_instance = software_instance_list[0].getObject()
elif software_instance_count > 1:
# XXX do not prevent the system to work if one partition is broken
raise NotImplementedError, "Too many instances %s linked to %s" % \
([x.path for x in software_instance_list],
computer_partition_document.getRelativeUrl())
if software_instance is not None:
state = software_instance.getSlapState()
if state == "stop_requested":
slap_partition._requested_state = 'stopped'
if state == "start_requested":
slap_partition._requested_state = 'started'
slap_partition._software_release_document = SoftwareRelease(
software_release=software_instance.getRootSoftwareReleaseUrl(),
computer_guid=computer_id)
parameter_dict = self._getSalePackingListLineAsSoftwareInstance(
movement)
slap_partition._need_modification = 1
parameter_dict = self._getSoftwareInstanceAsParameterDict(
software_instance)
# software instance has to define an xml parameter
slap_partition._parameter_dict = self._instanceXmlToDict(
parameter_dict.pop('xml'))
......@@ -526,101 +539,8 @@ class SlapTool(BaseTool):
slave_instance_dict.pop("xml")))
slap_partition._parameter_dict.update(parameter_dict)
# Apply state and buildout run conditions
if movement.getResource() == \
portal_preferences.getPreferredInstanceSetupResource():
if movement.getSimulationState() in ('confirmed', 'started',):
slap_partition._requested_state = 'stopped'
slap_partition._need_modification = 1
elif movement.getSimulationState() == 'stopped':
slap_partition._requested_state = 'stopped'
if update_movement is not None:
slap_partition._need_modification = 1
elif movement.getSimulationState() == 'delivered':
slap_partition._requested_state = 'destroyed'
else:
raise NotImplementedError, "Unexpected state %s" % \
movement.getSimulationState()
elif movement.getResource() == \
portal_preferences.getPreferredInstanceHostingResource():
if movement.getSimulationState() == 'confirmed':
slap_partition._requested_state = 'started'
slap_partition._need_modification = 1
elif movement.getSimulationState() == 'started':
slap_partition._requested_state = 'started'
slap_partition._need_modification = \
self._hasSlaveInstanceNeedModification(computer_partition_document)
if update_movement is not None:
slap_partition._need_modification = 1
elif movement.getSimulationState() == 'stopped':
slap_partition._requested_state = 'stopped'
slap_partition._need_modification = 1
elif movement.getSimulationState() == 'delivered':
slap_partition._requested_state = 'stopped'
if update_movement is not None:
slap_partition._need_modification = 1
else:
raise NotImplementedError, "Unexpected state %s" % \
movement.getSimulationState()
elif movement.getResource() == \
portal_preferences.getPreferredInstanceCleanupResource():
if movement.getSimulationState() in ('confirmed', 'started',
'stopped'):
slap_partition._need_modification = 1
else:
raise NotImplementedError, "Unexpected resource%s" % \
movement.getResource()
return slap_partition
def _hasSlaveInstanceNeedModification(self, computer_partition_document):
"""
Check if modification is needed for...
"""
portal = self.getPortalObject()
portal_preferences = portal.portal_preferences
hosting_service = portal.restrictedTraverse(
portal_preferences.getPreferredInstanceHostingResource())
setup_service = portal.restrictedTraverse(
portal_preferences.getPreferredInstanceSetupResource())
update_service = portal.restrictedTraverse(
portal_preferences.getPreferredInstanceUpdateResource())
global_query_kw = dict(aggregate_portal_type="Slave Instance",
default_aggregate_uid=computer_partition_document.getUid(),)
hosting_query = ComplexQuery(Query(simulation_state=["confirmed", "stopped"]),
Query(default_resource_uid=hosting_service.getUid()),
operator="AND")
setup_query = ComplexQuery(Query(simulation_state=["confirmed", "started"]),
Query(default_resource_uid=setup_service.getUid()),
operator="AND")
update_query = ComplexQuery(Query(simulation_state=["confirmed"]),
Query(default_resource_uid=update_service.getUid()),
operator="AND")
query = ComplexQuery(hosting_query,
setup_query,
update_query,
operator="OR")
# Use getTrackingList
catalog_result = portal.portal_catalog(
portal_type='Sale Packing List Line',
limit=1,
query=query, **global_query_kw)
return len(catalog_result)
@convertToREST
def _supplySupply(self, url, computer_id, state):
"""
......@@ -869,13 +789,7 @@ class SlapTool(BaseTool):
sla_xml = etree.tostring(instance, pretty_print=True,
xml_declaration=True, encoding='utf-8')
if shared:
instance_portal_type = "Slave Instance"
else:
instance_portal_type = "Software Instance"
cleanup_resource = self.getPortalObject().portal_preferences\
.getPreferredInstanceCleanupResource()
portal = self.getPortalObject()
if computer_id and computer_partition_id:
# requested by Software Instance, there is already top part of tree
software_instance_document = self.\
......@@ -889,22 +803,9 @@ class SlapTool(BaseTool):
shared=shared,
sla_xml=sla_xml,
state=state)
# Get requested software instance
requested_software_instance = software_instance_document.portal_catalog.\
getResultValue(
portal_type=instance_portal_type,
source_reference=software_type,
# predecessor_related_uid is inconsistent with
# SoftwareInstancae.requestSoftwareInstance but in this case it
# is assumed, that data are correct
predecessor_related_uid=software_instance_document.getUid(),
title=partition_reference,
)
else:
# requested as root, so done by human
person = self.getPortalObject()\
.ERP5Site_getAuthenticatedMemberPersonValue()
person = portal.ERP5Site_getAuthenticatedMemberPersonValue()
person.requestSoftwareInstance(software_release=software_release,
software_type=software_type,
software_title=partition_reference,
......@@ -912,53 +813,18 @@ class SlapTool(BaseTool):
instance_xml=instance_xml,
sla_xml=sla_xml,
state=state)
requested_software_instance = None
for software_instance in person.portal_catalog(
portal_type=instance_portal_type,
# In order be in sync with defaults of person.
# requestSoftwareInstance it is required to default here
# too
source_reference=software_type or 'RootSoftwareInstance',
title=partition_reference,
):
try:
cleanup_delivery_line = software_instance\
.Item_getInstancePackingListLine(cleanup_resource)
except ValueError:
requested_software_instance = software_instance
break
else:
if cleanup_delivery_line.getSimulationState() != 'delivered':
requested_software_instance = software_instance
break
if requested_software_instance is None:
requested_software_instance_url = self.REQUEST.get('request_instance')
if requested_software_instance_url is None:
raise SoftwareInstanceNotReady
else:
query_kw = {}
if shared:
# Provide precise reference when search for a slave.
query_kw['slave_reference'] = requested_software_instance.getReference()
movement = self._getSalePackingListLineForComputerPartition(
requested_software_instance, **query_kw)
if movement is None:
requested_software_instance = portal.restrictedTraverse(requested_software_instance_url)
if not requested_software_instance.getAggregate(portal_type="Computer Partition"):
raise SoftwareInstanceNotReady
parameter_dict = self._getSalePackingListLineAsSoftwareInstance(movement)
software_instance = SoftwareInstance(**parameter_dict)
if shared:
# XXX: Dirty hack
slave_instance = None
for slave_instance in parameter_dict.get("slave_instance_list", []):
if slave_instance['slave_title'] == partition_reference:
break
if slave_instance is not None:
software_instance._parameter_dict = self._instanceXmlToDict(
slave_instance.pop('xml'))
software_instance._connection_dict = self._instanceXmlToDict(
slave_instance.pop('connection_xml'))
return xml_marshaller.xml_marshaller.dumps(software_instance)
else:
parameter_dict = self._getSoftwareInstanceAsParameterDict(requested_software_instance)
software_instance = SoftwareInstance(**parameter_dict)
return xml_marshaller.xml_marshaller.dumps(software_instance)
####################################################
# Internals methods
......@@ -1014,16 +880,18 @@ class SlapTool(BaseTool):
computer_partition_document.getRelativeUrl())
raise NotFound, "No software instance found for: %s - %s" % (computer_id,
computer_partition_id)
packing_list_line = self._getSalePackingListLineForComputerPartition(
computer_partition_document,
slave_reference)
if packing_list_line is None:
raise NotFound, "No software instance found for: %s - %s" % (computer_id,
computer_partition_id)
else:
portal_type_list = ["Software Instance", "Slave Instance"]
software_instance = packing_list_line.getAggregateValue(
portal_type=portal_type_list)
query_kw = {
'validation_state': 'validated',
'portal_type': 'Slave Instance',
'default_aggregate_uid': computer_partition_document.getUid(),
}
if slave_reference is None:
query_kw['portal_type'] = "Software Instance"
else:
query_kw['reference'] = slave_reference
software_instance = self.getPortalObject().portal_catalog.getResultValue(**query_kw)
if software_instance is None:
raise NotFound, "No software instance found for: %s - %s" % (
computer_id, computer_partition_id)
......@@ -1031,14 +899,43 @@ class SlapTool(BaseTool):
return software_instance
@UnrestrictedMethod
def _getSalePackingListLineAsSoftwareInstance(self, sale_packing_list_line):
merged_dict = sale_packing_list_line.\
SalePackinListLine_asSoftwareInstnaceComputerPartitionMergedDict()
if merged_dict is None:
LOG('SlapTool._getSalePackingListLineAsSoftwareInstance', INFO,
'%s returned no information' % sale_packing_list_line.getRelativeUrl())
raise Unauthorized
return merged_dict
def _getSoftwareInstanceAsParameterDict(self, software_instance):
portal = software_instance.getPortalObject()
computer_partition = software_instance.getAggregateValue(portal_type="Computer Partition")
ip_list = []
for internet_protocol_address in computer_partition.contentValues(portal_type='Internet Protocol Address'):
ip_list.append((internet_protocol_address.getNetworkInterface(''), internet_protocol_address.getIpAddress()))
slave_instance_list = []
if (software_instance.getPortalType() == "Software Instance"):
append = slave_instance_list.append
slave_instance_sql_list = portal.portal_catalog(
default_aggregate_uid=computer_partition.getUid(),
portal_type='Slave Instance',
validation_state="validated",
)
for slave_instance in slave_instance_sql_list:
slave_instance = slave_instance.getObject()
# XXX Use catalog to filter more efficiently
if slave_instance.getSlapState() == "start_requested":
append({
'slave_title': slave_instance.getTitle(),
'slap_software_type': slave_instance.getSourceReference(),
'slave_reference': slave_instance.getReference(),
'xml': slave_instance.getTextContent(),
'connection_xml': slave_instance.getConnectionXml(),
})
return {
'xml': software_instance.getTextContent(),
'connection_xml': software_instance.getConnectionXml(),
'slap_computer_id': computer_partition.getParentValue().getReference(),
'slap_computer_partition_id': computer_partition.getReference(),
'slap_software_type': software_instance.getSourceReference(),
'slap_software_release_url': software_instance.getRootSoftwareReleaseUrl(),
'slave_instance_list': slave_instance_list,
'ip_list': ip_list,
}
@UnrestrictedMethod
def _getSoftwareReleaseValueListForComputer(self, computer_reference,
......@@ -1065,54 +962,6 @@ class SlapTool(BaseTool):
software_release_list.append(software_release_response)
return software_release_list
def _getSalePackingListLineForComputerPartition(self,
computer_partition_document,
slave_reference=None,
service_uid_list=None):
"""
Return latest meaningfull sale packing list related to a computer partition
document
"""
portal = self.getPortalObject()
portal_preferences = portal.portal_preferences
if service_uid_list is None:
service_uid_list = []
for service_relative_url in \
(portal_preferences.getPreferredInstanceSetupResource(),
portal_preferences.getPreferredInstanceHostingResource(),
portal_preferences.getPreferredInstanceCleanupResource(),
):
service = portal.restrictedTraverse(service_relative_url)
service_uid_list.append(service.getUid())
# Get associated software release
state_list = []
state_list.extend(portal.getPortalCurrentInventoryStateList())
state_list.extend(portal.getPortalReservedInventoryStateList())
state_list.extend(portal.getPortalTransitInventoryStateList())
if slave_reference is not None:
query = ComplexQuery(Query(aggregate_reference=slave_reference),
Query(default_aggregate_uid=computer_partition_document.getUid()),
operator="AND")
else:
query = ComplexQuery(Query(aggregate_portal_type="Software Instance"),
Query(default_aggregate_uid=computer_partition_document.getUid()),
operator="AND")
# Use getTrackingList
catalog_result = portal.portal_catalog(
portal_type='Sale Packing List Line',
simulation_state=state_list,
default_resource_uid=service_uid_list,
sort_on=(('movement.start_date', 'DESC'),),
limit=1,
query=query
)
if len(catalog_result):
return catalog_result[0].getObject()
else:
return None
def _reportComputerUsage(self, computer, usage):
"""Stores usage report of a computer."""
usage_report_portal_type = 'Usage Report'
......
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