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): ...@@ -492,26 +492,39 @@ class SlapTool(BaseTool):
slap_partition._requested_state = 'destroyed' slap_partition._requested_state = 'destroyed'
slap_partition._need_modification = 0 slap_partition._need_modification = 0
if computer_partition_document.getSlapState() != 'busy': software_instance = None
update_movement = None
movement = None if computer_partition_document.getSlapState() == 'busy':
else: software_instance_list = portal.portal_catalog(
update_movement = self._getSalePackingListLineForComputerPartition( portal_type="Software Instance",
computer_partition_document, service_uid_list=[portal.restrictedTraverse(portal_preferences.getPreferredInstanceUpdateResource()).getUid()]) default_aggregate_uid=computer_partition_document.getUid(),
movement = self._getSalePackingListLineForComputerPartition( validation_state="validated",
computer_partition_document) limit=2,
if update_movement is not None: )
if update_movement.getSimulationState() != 'confirmed': software_instance_count = len(software_instance_list)
# only confirmed update movements are interesting if software_instance_count == 1:
update_movement = None software_instance = software_instance_list[0].getObject()
if movement is not None: elif software_instance_count > 1:
software_release_document = \ # XXX do not prevent the system to work if one partition is broken
movement.getAggregateValue(portal_type='Software Release') raise NotImplementedError, "Too many instances %s linked to %s" % \
slap_partition._software_release_document = SoftwareRelease( ([x.path for x in software_instance_list],
software_release=software_release_document.getUrlString(), 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) 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 # software instance has to define an xml parameter
slap_partition._parameter_dict = self._instanceXmlToDict( slap_partition._parameter_dict = self._instanceXmlToDict(
parameter_dict.pop('xml')) parameter_dict.pop('xml'))
...@@ -526,101 +539,8 @@ class SlapTool(BaseTool): ...@@ -526,101 +539,8 @@ class SlapTool(BaseTool):
slave_instance_dict.pop("xml"))) slave_instance_dict.pop("xml")))
slap_partition._parameter_dict.update(parameter_dict) 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 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 @convertToREST
def _supplySupply(self, url, computer_id, state): def _supplySupply(self, url, computer_id, state):
""" """
...@@ -869,13 +789,7 @@ class SlapTool(BaseTool): ...@@ -869,13 +789,7 @@ class SlapTool(BaseTool):
sla_xml = etree.tostring(instance, pretty_print=True, sla_xml = etree.tostring(instance, pretty_print=True,
xml_declaration=True, encoding='utf-8') xml_declaration=True, encoding='utf-8')
if shared: portal = self.getPortalObject()
instance_portal_type = "Slave Instance"
else:
instance_portal_type = "Software Instance"
cleanup_resource = self.getPortalObject().portal_preferences\
.getPreferredInstanceCleanupResource()
if computer_id and computer_partition_id: if computer_id and computer_partition_id:
# requested by Software Instance, there is already top part of tree # requested by Software Instance, there is already top part of tree
software_instance_document = self.\ software_instance_document = self.\
...@@ -889,22 +803,9 @@ class SlapTool(BaseTool): ...@@ -889,22 +803,9 @@ class SlapTool(BaseTool):
shared=shared, shared=shared,
sla_xml=sla_xml, sla_xml=sla_xml,
state=state) 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: else:
# requested as root, so done by human # requested as root, so done by human
person = self.getPortalObject()\ person = portal.ERP5Site_getAuthenticatedMemberPersonValue()
.ERP5Site_getAuthenticatedMemberPersonValue()
person.requestSoftwareInstance(software_release=software_release, person.requestSoftwareInstance(software_release=software_release,
software_type=software_type, software_type=software_type,
software_title=partition_reference, software_title=partition_reference,
...@@ -912,53 +813,18 @@ class SlapTool(BaseTool): ...@@ -912,53 +813,18 @@ class SlapTool(BaseTool):
instance_xml=instance_xml, instance_xml=instance_xml,
sla_xml=sla_xml, sla_xml=sla_xml,
state=state) state=state)
requested_software_instance = None
for software_instance in person.portal_catalog( requested_software_instance_url = self.REQUEST.get('request_instance')
portal_type=instance_portal_type, if requested_software_instance_url is None:
# 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:
raise SoftwareInstanceNotReady raise SoftwareInstanceNotReady
else: else:
query_kw = {} requested_software_instance = portal.restrictedTraverse(requested_software_instance_url)
if shared: if not requested_software_instance.getAggregate(portal_type="Computer Partition"):
# 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:
raise SoftwareInstanceNotReady raise SoftwareInstanceNotReady
parameter_dict = self._getSalePackingListLineAsSoftwareInstance(movement) else:
software_instance = SoftwareInstance(**parameter_dict) parameter_dict = self._getSoftwareInstanceAsParameterDict(requested_software_instance)
software_instance = SoftwareInstance(**parameter_dict)
if shared: return xml_marshaller.xml_marshaller.dumps(software_instance)
# 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)
#################################################### ####################################################
# Internals methods # Internals methods
...@@ -1014,16 +880,18 @@ class SlapTool(BaseTool): ...@@ -1014,16 +880,18 @@ class SlapTool(BaseTool):
computer_partition_document.getRelativeUrl()) computer_partition_document.getRelativeUrl())
raise NotFound, "No software instance found for: %s - %s" % (computer_id, raise NotFound, "No software instance found for: %s - %s" % (computer_id,
computer_partition_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: else:
portal_type_list = ["Software Instance", "Slave Instance"] query_kw = {
software_instance = packing_list_line.getAggregateValue( 'validation_state': 'validated',
portal_type=portal_type_list) '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: if software_instance is None:
raise NotFound, "No software instance found for: %s - %s" % ( raise NotFound, "No software instance found for: %s - %s" % (
computer_id, computer_partition_id) computer_id, computer_partition_id)
...@@ -1031,14 +899,43 @@ class SlapTool(BaseTool): ...@@ -1031,14 +899,43 @@ class SlapTool(BaseTool):
return software_instance return software_instance
@UnrestrictedMethod @UnrestrictedMethod
def _getSalePackingListLineAsSoftwareInstance(self, sale_packing_list_line): def _getSoftwareInstanceAsParameterDict(self, software_instance):
merged_dict = sale_packing_list_line.\ portal = software_instance.getPortalObject()
SalePackinListLine_asSoftwareInstnaceComputerPartitionMergedDict() computer_partition = software_instance.getAggregateValue(portal_type="Computer Partition")
if merged_dict is None:
LOG('SlapTool._getSalePackingListLineAsSoftwareInstance', INFO, ip_list = []
'%s returned no information' % sale_packing_list_line.getRelativeUrl()) for internet_protocol_address in computer_partition.contentValues(portal_type='Internet Protocol Address'):
raise Unauthorized ip_list.append((internet_protocol_address.getNetworkInterface(''), internet_protocol_address.getIpAddress()))
return merged_dict
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 @UnrestrictedMethod
def _getSoftwareReleaseValueListForComputer(self, computer_reference, def _getSoftwareReleaseValueListForComputer(self, computer_reference,
...@@ -1065,54 +962,6 @@ class SlapTool(BaseTool): ...@@ -1065,54 +962,6 @@ class SlapTool(BaseTool):
software_release_list.append(software_release_response) software_release_list.append(software_release_response)
return software_release_list 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): def _reportComputerUsage(self, computer, usage):
"""Stores usage report of a computer.""" """Stores usage report of a computer."""
usage_report_portal_type = 'Usage Report' 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