Commit b3300d0f authored by Romain Courteaud's avatar Romain Courteaud

slapos_slap_tool: support for the virtual master logic

A project reference is required to create a compute node.

Add compatibility with the user request
Console client does not send a project reference.
Try to guess it for simple cases
parent a22f28a8
......@@ -16,7 +16,9 @@ def getComputeNodeReferenceAndUserId(item):
if partition is not None:
compute_node = partition.getParentValue()
if compute_node is not None and compute_node.getValidationState() == 'validated':
if (compute_node is not None) and \
(compute_node.getPortalType() == 'Compute Node') and \
(compute_node.getValidationState() == 'validated'):
return compute_node, compute_node.getReference(), compute_node.getUserId()
return None, None, None
......
......@@ -6,12 +6,6 @@
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SlapOSSlapTool</string> </value>
......@@ -55,28 +49,13 @@
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
......@@ -89,7 +68,7 @@
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
......@@ -98,7 +77,7 @@
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
......
# -*- coding: utf-8 -*-
# Copyright (c) 2002-2012 Nexedi SA and Contributors. All Rights Reserved.
from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixin
from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixin, TemporaryAlarmScript
from DateTime import DateTime
from App.Common import rfc1123_date
......@@ -53,17 +53,16 @@ class TestSlapOSSlapToolMixin(SlapOSTestCaseMixin):
SlapOSTestCaseMixin.afterSetUp(self)
self.portal_slap = self.portal.portal_slap
self.project = self.addProject()
# Prepare compute_node
self.compute_node = self.portal.compute_node_module.template_compute_node\
.Base_createCloneDocument(batch_mode=1)
self.compute_node = self.portal.compute_node_module\
.newContent(portal_type="Compute Node")
self.compute_node.edit(
title="Compute Node %s" % self.new_id,
reference="TESTCOMP-%s" % self.new_id
reference="TESTCOMP-%s" % self.new_id,
follow_up_value=self.project
)
if getattr(self, "person", None) is not None:
self.compute_node.edit(
source_administration_value=getattr(self, "person", None),
)
self.compute_node.validate()
self._addCertificateLogin(self.compute_node)
......@@ -83,7 +82,7 @@ class TestSlapOSSlapToolMixin(SlapOSTestCaseMixin):
class TestSlapOSSlapToolgetFullComputerInformation(TestSlapOSSlapToolMixin):
def test_activate_getFullComputerInformation_first_access(self):
self._makeComplexComputeNode(with_slave=True)
self._makeComplexComputeNode(self.project, with_slave=True)
self.portal.REQUEST['disable_isTestRun'] = True
self.login(self.compute_node_user_id)
......@@ -202,7 +201,11 @@ class TestSlapOSSlapToolgetFullComputerInformation(TestSlapOSSlapToolMixin):
# Remove the slave link to the partition
# Compute Node should loose permission to access the slave instance
self.logout()
self.login()
self.start_requested_slave_instance.setAggregate('')
self.logout()
self.login(self.compute_node_user_id)
self.commit()
# 7th access
......@@ -253,7 +256,7 @@ class TestSlapOSSlapToolgetFullComputerInformation(TestSlapOSSlapToolMixin):
class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
def test_getFullComputerInformation(self):
self._makeComplexComputeNode(with_slave=True)
self._makeComplexComputeNode(self.project, with_slave=True)
partition_1_root_instance_title = self.compute_node.partition1.getAggregateRelatedValue(
portal_type='Software Instance').getSpecialiseValue().getTitle()
......@@ -741,7 +744,7 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
'recmethod': 'reportComputeNodeBang'}])
def test_computerBang(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
self.compute_node_bang_simulator = tempfile.mkstemp()[1]
try:
self.login(self.compute_node_user_id)
......@@ -793,7 +796,7 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
os.unlink(self.compute_node_load_configuration_simulator)
def test_not_accessed_getSoftwareInstallationStatus(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
self.compute_node_bang_simulator = tempfile.mkstemp()[1]
self.login(self.compute_node_user_id)
created_at = rfc1123_date(DateTime())
......@@ -851,7 +854,7 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
"http://example.org/foo", self.compute_node_id)
def test_destroyedSoftwareRelease_noDestroyRequested(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
self.login(self.compute_node_user_id)
self.assertRaises(NotFound,
self.portal_slap.destroyedSoftwareRelease,
......@@ -859,7 +862,7 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
self.compute_node_id)
def test_destroyedSoftwareRelease_destroyRequested(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
self.login(self.compute_node_user_id)
destroy_requested = self.destroy_requested_software_installation
self.assertEqual(destroy_requested.getValidationState(), "validated")
......@@ -868,7 +871,7 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
self.assertEqual(destroy_requested.getValidationState(), "invalidated")
def test_availableSoftwareRelease(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
self.compute_node_bang_simulator = tempfile.mkstemp()[1]
self.login(self.compute_node_user_id)
software_installation = self.start_requested_software_installation
......@@ -917,7 +920,7 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
self.assertXMLEqual(expected_xml, got_xml)
def test_buildingSoftwareRelease(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
self.compute_node_bang_simulator = tempfile.mkstemp()[1]
self.login(self.compute_node_user_id)
software_installation = self.start_requested_software_installation
......@@ -966,7 +969,7 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
self.assertXMLEqual(expected_xml, got_xml)
def test_softwareReleaseError(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
self.compute_node_bang_simulator = tempfile.mkstemp()[1]
self.login(self.compute_node_user_id)
software_installation = self.start_requested_software_installation
......@@ -1119,7 +1122,7 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
def test_getComputerPartitionCertificate(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
self.login(self.start_requested_software_instance.getUserId())
......@@ -1153,7 +1156,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
self.assertXMLEqual(expected_xml, got_xml)
def test_getFullComputerInformation(self):
self._makeComplexComputeNode(with_slave=True)
self._makeComplexComputeNode(self.project, with_slave=True)
self.login(self.start_requested_software_instance.getUserId())
response = self.portal_slap.getFullComputerInformation(self.compute_node_id)
self.assertEqual(200, response.status)
......@@ -1294,7 +1297,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
self.assertXMLEqual(expected_xml, got_xml)
def test_getComputerPartitionStatus(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
created_at = rfc1123_date(DateTime())
......@@ -1343,7 +1346,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
self.assertXMLEqual(expected_xml, got_xml)
def test_getComputerPartitionStatus_visited(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
created_at = rfc1123_date(DateTime())
......@@ -1395,7 +1398,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
self.assertXMLEqual(expected_xml, got_xml)
def test_registerComputerPartition_withSlave(self):
self._makeComplexComputeNode(with_slave=True)
self._makeComplexComputeNode(self.project, with_slave=True)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
self.login(self.start_requested_software_instance.getUserId())
......@@ -1525,7 +1528,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
self.assertXMLEqual(expected_xml, got_xml)
def test_registerComputerPartition(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
self.login(self.start_requested_software_instance.getUserId())
......@@ -1644,7 +1647,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
'recmethod': 'updateConnection'}])
def test_setConnectionXml_withSlave(self):
self._makeComplexComputeNode(with_slave=True)
self._makeComplexComputeNode(self.project, with_slave=True)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
slave_reference = self.start_requested_slave_instance.getReference()
......@@ -1678,7 +1681,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
os.unlink(self.instance_update_connection_simulator)
def test_setConnectionXml(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
connection_xml = """<marshal>
......@@ -1711,7 +1714,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
os.unlink(self.instance_update_connection_simulator)
def test_softwareInstanceError(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
self.login(self.start_requested_software_instance.getUserId())
......@@ -1758,7 +1761,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
self.assertXMLEqual(expected_xml, got_xml)
def test_softwareInstanceError_twice(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
self.login(self.start_requested_software_instance.getUserId())
......@@ -1862,7 +1865,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
'recmethod': 'bang'}])
def test_softwareInstanceBang(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
self.instance_bang_simulator = tempfile.mkstemp()[1]
try:
partition_id = self.start_requested_software_instance.getAggregateValue(
......@@ -1924,7 +1927,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
'recmethod': 'rename'}])
def test_softwareInstanceRename(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
self.instance_rename_simulator = tempfile.mkstemp()[1]
try:
partition_id = self.start_requested_software_instance.getAggregateValue(
......@@ -1944,7 +1947,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
os.unlink(self.instance_rename_simulator)
def test_destroyedComputePartition(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
partition_id = self.destroy_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
ssl_key = self.destroy_requested_software_instance.getSslKey()
......@@ -1972,7 +1975,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
'recmethod': 'requestInstance'}])
def test_request_withSlave(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
self.instance_request_simulator = tempfile.mkstemp()[1]
try:
partition_id = self.start_requested_software_instance.getAggregateValue(
......@@ -1990,6 +1993,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
filter_xml='<marshal><dictionary id="i2"/></marshal>',
state='<marshal><string>started</string></marshal>',
shared_xml='<marshal><bool>1</bool></marshal>',
project_reference=self.project.getReference()
)
self.assertEqual(408, response.status)
self.assertEqual('private',
......@@ -2001,13 +2005,15 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
'state': 'started',
'sla_xml': "<?xml version='1.0' encoding='utf-8'?>\n<instance/>\n",
'software_type': 'req_type',
'shared': True})
'shared': True,
'project_reference': self.project.getReference()
})
finally:
if os.path.exists(self.instance_request_simulator):
os.unlink(self.instance_request_simulator)
def test_request(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
self.instance_request_simulator = tempfile.mkstemp()[1]
try:
partition_id = self.start_requested_software_instance.getAggregateValue(
......@@ -2025,6 +2031,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
filter_xml='<marshal><dictionary id="i2"/></marshal>',
state='<marshal><string>started</string></marshal>',
shared_xml='<marshal><bool>0</bool></marshal>',
project_reference=self.project.getReference()
)
self.assertEqual(408, response.status)
self.assertEqual('private',
......@@ -2036,13 +2043,15 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
'state': 'started',
'sla_xml': "<?xml version='1.0' encoding='utf-8'?>\n<instance/>\n",
'software_type': 'req_type',
'shared': False})
'shared': False,
'project_reference': self.project.getReference()
})
finally:
if os.path.exists(self.instance_request_simulator):
os.unlink(self.instance_request_simulator)
def test_request_stopped(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
self.instance_request_simulator = tempfile.mkstemp()[1]
try:
partition_id = self.stop_requested_software_instance.getAggregateValue(
......@@ -2060,6 +2069,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
filter_xml='<marshal><dictionary id="i2"/></marshal>',
state='<marshal><string>started</string></marshal>',
shared_xml='<marshal><bool>0</bool></marshal>',
project_reference=self.project.getReference()
)
self.assertEqual(408, response.status)
self.assertEqual('private',
......@@ -2071,13 +2081,15 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
'state': 'stopped',
'sla_xml': "<?xml version='1.0' encoding='utf-8'?>\n<instance/>\n",
'software_type': 'req_type',
'shared': False})
'shared': False,
'project_reference': self.project.getReference()
})
finally:
if os.path.exists(self.instance_request_simulator):
os.unlink(self.instance_request_simulator)
def test_updateInstanceSuccessorList(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
......@@ -2133,7 +2145,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
self.start_requested_software_instance.getSuccessorTitleList())
def test_updateInstanceSuccessorList_one_child(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
......@@ -2168,7 +2180,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
self.start_requested_software_instance.getSuccessorTitleList())
def test_updateInstanceSuccessorList_no_child(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
......@@ -2205,7 +2217,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
self.start_requested_software_instance.getSuccessorTitleList())
def test_stoppedComputePartition(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
self.login(self.start_requested_software_instance.getUserId())
......@@ -2251,7 +2263,7 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
self.assertXMLEqual(expected_xml, got_xml)
def test_startedComputePartition(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
self.login(self.start_requested_software_instance.getUserId())
......@@ -2298,33 +2310,23 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
def test_getSoftwareReleaseListFromSoftwareProduct(self):
new_id = self.generateNewId()
software_product = self._makeSoftwareProduct(new_id)
software_product = self._makeSoftwareProduct(self.project, new_id=new_id,
url='http://example.org/1.cfg')
# 2 published software releases
software_release1 = self._makeSoftwareRelease(new_id)
software_release2 = self._makeSoftwareRelease(self.generateNewId())
software_release1.publish()
software_release2.publish()
# 1 released software release, should not appear
software_release3 = self._makeSoftwareRelease(new_id)
self.assertTrue(software_release3.getValidationState() == 'released')
software_release1 = software_product.contentValues(portal_type='Software Product Release Variation')[0]
software_release2 = self._makeSoftwareRelease(software_product, url='http://example.org/2.cfg')
software_release1.edit(
aggregate_value=software_product.getRelativeUrl(),
url_string='http://example.org/1.cfg',
effective_date=DateTime()
)
software_release2.edit(
aggregate_value=software_product.getRelativeUrl(),
url_string='http://example.org/2.cfg',
effective_date=DateTime()
)
software_release3.edit(
aggregate_value=software_product.getRelativeUrl(),
url_string='http://example.org/3.cfg'
)
self.tic()
response = self.portal_slap.getSoftwareReleaseListFromSoftwareProduct(
software_product.getReference())
self.project.getReference(),
software_product_reference=software_product.getReference())
got_xml = etree.tostring(etree.fromstring(response),
pretty_print=True, encoding="UTF-8", xml_declaration=True)
expected_xml = """\
......@@ -2335,39 +2337,32 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
<string>%s</string>
</list>
</marshal>
""" % (software_release2.getUrlString(), software_release1.getUrlString())
""" % (software_release1.getUrlString(), software_release2.getUrlString())
self.assertXMLEqual(expected_xml, got_xml)
def test_getSoftwareReleaseListFromSoftwareProduct_effectiveDate(self):
new_id = self.generateNewId()
software_product = self._makeSoftwareProduct(new_id)
software_product = self._makeSoftwareProduct(self.project, new_id=new_id,
url='http://example.org/1.cfg')
# 3 published software releases
software_release1 = self._makeSoftwareRelease(new_id)
software_release2 = self._makeSoftwareRelease(self.generateNewId())
software_release3 = self._makeSoftwareRelease(self.generateNewId())
software_release1.publish()
software_release2.publish()
software_release3.publish()
software_release1 = software_product.contentValues(portal_type="Software Product Release Variation")[0]
software_release2 = self._makeSoftwareRelease(software_product, url='http://example.org/2.cfg')
software_release3 = self._makeSoftwareRelease(software_product, url='http://example.org/3.cfg')
software_release1.edit(
aggregate_value=software_product.getRelativeUrl(),
url_string='http://example.org/1.cfg',
effective_date=(DateTime() - 1)
)
# Should not be considered yet!
software_release2.edit(
aggregate_value=software_product.getRelativeUrl(),
url_string='http://example.org/2.cfg',
effective_date=(DateTime() + 1)
)
software_release3.edit(
aggregate_value=software_product.getRelativeUrl(),
url_string='http://example.org/3.cfg',
effective_date=DateTime()
)
self.tic()
response = self.portal_slap.getSoftwareReleaseListFromSoftwareProduct(
software_product.getReference())
self.project.getReference(),
software_product_reference=software_product.getReference())
# check returned XML
got_xml = etree.tostring(etree.fromstring(response),
pretty_print=True, encoding="UTF-8", xml_declaration=True)
......@@ -2386,10 +2381,11 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
def test_getSoftwareReleaseListFromSoftwareProduct_emptySoftwareProduct(self):
new_id = self.generateNewId()
software_product = self._makeSoftwareProduct(new_id)
software_product = self._makeSoftwareProduct(self.project, new_id=new_id)
response = self.portal_slap.getSoftwareReleaseListFromSoftwareProduct(
software_product.getReference())
self.project.getReference(),
software_product_reference=software_product.getReference())
got_xml = etree.tostring(etree.fromstring(response),
pretty_print=True, encoding="UTF-8", xml_declaration=True)
expected_xml = """\
......@@ -2402,7 +2398,8 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
def test_getSoftwareReleaseListFromSoftwareProduct_NoSoftwareProduct(self):
response = self.portal_slap.getSoftwareReleaseListFromSoftwareProduct(
'Can I has a nonexistent software product?')
self.project.getReference(),
software_product_reference='Can I has a nonexistent software product?')
got_xml = etree.tostring(etree.fromstring(response),
pretty_print=True, encoding="UTF-8", xml_declaration=True)
expected_xml = """\
......@@ -2415,31 +2412,17 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
def test_getSoftwareReleaseListFromSoftwareProduct_fromUrl(self):
new_id = self.generateNewId()
software_product = self._makeSoftwareProduct(new_id)
software_product = self._makeSoftwareProduct(self.project, new_id=new_id,
url='http://example.org/1.cfg')
# 2 published software releases
software_release1 = self._makeSoftwareRelease(new_id)
software_release2 = self._makeSoftwareRelease(self.generateNewId())
software_release1.publish()
software_release2.publish()
# 1 released software release, should not appear
software_release3 = self._makeSoftwareRelease(new_id)
self.assertTrue(software_release3.getValidationState() == 'released')
software_release1.edit(
aggregate_value=software_product.getRelativeUrl(),
url_string='http://example.org/1.cfg'
)
software_release2.edit(
aggregate_value=software_product.getRelativeUrl(),
url_string='http://example.org/2.cfg'
)
software_release3.edit(
aggregate_value=software_product.getRelativeUrl(),
url_string='http://example.org/3.cfg'
)
software_release1 = software_product.contentValues(portal_type='Software Product Release Variation')[0]
software_release2 = self._makeSoftwareRelease(software_product, url='http://example.org/2.cfg')
self.tic()
response = self.portal_slap.getSoftwareReleaseListFromSoftwareProduct(
software_release_url=software_release2.getUrlString())
self.project.getReference(),
software_release_url=software_release2.getUrlString())
# check returned XML
got_xml = etree.tostring(etree.fromstring(response),
pretty_print=True, encoding="UTF-8", xml_declaration=True)
......@@ -2451,18 +2434,26 @@ class TestSlapOSSlapToolInstanceAccess(TestSlapOSSlapToolMixin):
<string>%s</string>
</list>
</marshal>
""" % (software_release2.getUrlString(), software_release1.getUrlString())
""" % (software_release1.getUrlString(), software_release2.getUrlString())
self.assertXMLEqual(expected_xml, got_xml)
class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
def afterSetUp(self):
password = "%s-1Aa$" % self.generateNewId()
TestSlapOSSlapToolMixin.afterSetUp(self)
password = "%s-1Aa$" % self.generateNewId()
reference = 'test_%s' % self.generateNewId()
person = self.portal.person_module.newContent(portal_type='Person',
person = self.portal.person_module.newContent(
portal_type='Person',
title=reference,
reference=reference)
person.newContent(portal_type='Assignment', role='member').open()
reference=reference
)
person.newContent(
portal_type='Assignment',
function='customer',
destination_project_value=self.project
).open()
person.newContent(portal_type='ERP5 Login',
reference=reference, password=password).validate()
......@@ -2470,7 +2461,7 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
self.person = person
self.person_reference = person.getReference()
self.person_user_id = person.getUserId()
TestSlapOSSlapToolMixin.afterSetUp(self)
self.tic()
def test_not_accessed_getComputerStatus(self):
self.login(self.person_user_id)
......@@ -2596,7 +2587,7 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
os.unlink(self.compute_node_bang_simulator)
def test_getComputerPartitionStatus(self):
self._makeComplexComputeNode()
self._makeComplexComputeNode(self.project)
self.login(self.person_user_id)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
......@@ -2646,7 +2637,7 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
self.assertXMLEqual(expected_xml, got_xml)
def test_getComputerPartitionStatus_visited(self):
self._makeComplexComputeNode(person=self.person)
self._makeComplexComputeNode(self.project, person=self.person)
self.login(self.person_user_id)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
......@@ -2700,7 +2691,7 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
self.assertXMLEqual(expected_xml, got_xml)
def test_registerComputerPartition_withSlave(self):
self._makeComplexComputeNode(person=self.person, with_slave=True)
self._makeComplexComputeNode(self.project, person=self.person, with_slave=True)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
self.login(self.person_user_id)
......@@ -2830,7 +2821,7 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
self.assertXMLEqual(expected_xml, got_xml)
def test_registerComputerPartition(self):
self._makeComplexComputeNode(person=self.person)
self._makeComplexComputeNode(self.project, person=self.person)
partition_id = self.start_requested_software_instance.getAggregateValue(
portal_type='Compute Partition').getReference()
self.login(self.person_user_id)
......@@ -2949,7 +2940,7 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
'recmethod': 'bang'}])
def test_softwareInstanceBang(self):
self._makeComplexComputeNode(person=self.person)
self._makeComplexComputeNode(self.project, person=self.person)
self.instance_bang_simulator = tempfile.mkstemp()[1]
try:
partition_id = self.start_requested_software_instance.getAggregateValue(
......@@ -3013,7 +3004,7 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
'recmethod': 'rename'}])
def test_softwareInstanceRename(self):
self._makeComplexComputeNode(person=self.person)
self._makeComplexComputeNode(self.project, person=self.person)
self.instance_rename_simulator = tempfile.mkstemp()[1]
try:
partition_id = self.start_requested_software_instance.getAggregateValue(
......@@ -3053,6 +3044,7 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
filter_xml='<marshal><dictionary id="i2"/></marshal>',
state='<marshal><string>started</string></marshal>',
shared_xml='<marshal><bool>1</bool></marshal>',
project_reference=self.project.getReference()
)
self.assertEqual(408, response.status)
self.assertEqual('private',
......@@ -3064,7 +3056,9 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
'state': 'started',
'sla_xml': "<?xml version='1.0' encoding='utf-8'?>\n<instance/>\n",
'software_type': 'req_type',
'shared': True})
'shared': True,
'project_reference': self.project.getReference()
})
finally:
if os.path.exists(self.instance_request_simulator):
os.unlink(self.instance_request_simulator)
......@@ -3083,6 +3077,39 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
filter_xml='<marshal><dictionary id="i2"/></marshal>',
state='<marshal><string>started</string></marshal>',
shared_xml='<marshal><bool>0</bool></marshal>',
project_reference=self.project.getReference()
)
self.assertEqual(408, response.status)
self.assertEqual('private',
response.headers.get('cache-control'))
self.assertInstanceRequestSimulator((), {
'instance_xml': "<?xml version='1.0' encoding='utf-8'?>\n<instance/>\n",
'software_title': 'req_reference',
'software_release': 'req_release',
'state': 'started',
'sla_xml': "<?xml version='1.0' encoding='utf-8'?>\n<instance/>\n",
'software_type': 'req_type',
'shared': False,
'project_reference': self.project.getReference()
})
finally:
if os.path.exists(self.instance_request_simulator):
os.unlink(self.instance_request_simulator)
def test_requestWithoutProjectReference(self):
self.instance_request_simulator = tempfile.mkstemp()[1]
try:
self.login(self.person_user_id)
self.person.requestSoftwareInstance = Simulator(
self.instance_request_simulator, 'requestSoftwareInstance')
response = self.portal_slap.requestComputerPartition(
software_release='req_release',
software_type='req_type',
partition_reference='req_reference',
partition_parameter_xml='<marshal><dictionary id="i2"/></marshal>',
filter_xml='<marshal><dictionary id="i2"/></marshal>',
state='<marshal><string>started</string></marshal>',
shared_xml='<marshal><bool>0</bool></marshal>'
)
self.assertEqual(408, response.status)
self.assertEqual('private',
......@@ -3094,7 +3121,9 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
'state': 'started',
'sla_xml': "<?xml version='1.0' encoding='utf-8'?>\n<instance/>\n",
'software_type': 'req_type',
'shared': False})
'shared': False,
'project_reference': self.project.getReference()
})
finally:
if os.path.exists(self.instance_request_simulator):
os.unlink(self.instance_request_simulator)
......@@ -3105,19 +3134,21 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
default_email_coordinate_text="%s@example.org" % self.person.getReference(),
career_role='member',
)
self._makeComplexComputeNode(person=self.person)
self._makeComplexComputeNode(self.project, person=self.person)
self.start_requested_software_instance.updateLocalRolesOnSecurityGroups()
self.tic()
self.login(self.person_user_id)
response = self.portal_slap.requestComputerPartition(
software_release=self.start_requested_software_instance.getUrlString(),
software_type=self.start_requested_software_instance.getSourceReference(),
partition_reference=self.start_requested_software_instance.getTitle(),
partition_parameter_xml='<marshal><dictionary id="i2"/></marshal>',
filter_xml='<marshal><dictionary id="i2"/></marshal>',
state='<marshal><string>started</string></marshal>',
shared_xml='<marshal><bool>0</bool></marshal>',
)
with TemporaryAlarmScript(self.portal, 'Item_getSubscriptionStatus', "'subscribed'"):
response = self.portal_slap.requestComputerPartition(
software_release=self.start_requested_software_instance.getUrlString(),
software_type=self.start_requested_software_instance.getSourceReference(),
partition_reference=self.start_requested_software_instance.getTitle(),
partition_parameter_xml='<marshal><dictionary id="i2"/></marshal>',
filter_xml='<marshal><dictionary id="i2"/></marshal>',
state='<marshal><string>started</string></marshal>',
shared_xml='<marshal><bool>0</bool></marshal>',
project_reference=self.project.getReference()
)
self.assertEqual(type(response), str)
# check returned XML
got_xml = etree.tostring(etree.fromstring(response),
......@@ -3229,7 +3260,7 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
compute_node_id = 'Foo Compute Node'
compute_node_reference = 'live_comp_%s' % self.generateNewId()
self.portal.REQUEST.set('compute_node_reference', compute_node_reference)
response = self.portal_slap.requestComputer(compute_node_id)
response = self.portal_slap.requestComputer(compute_node_id, self.project.getReference())
got_xml = etree.tostring(etree.fromstring(response),
pretty_print=True, encoding="UTF-8", xml_declaration=True)
expected_xml = """\
......@@ -3248,7 +3279,8 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
""" % {'compute_node_id': compute_node_reference}
self.assertXMLEqual(expected_xml, got_xml)
self.assertRequestComputeNodeSimulator((), {'compute_node_title': compute_node_id})
self.assertRequestComputeNodeSimulator((), {'compute_node_title': compute_node_id,
'project_reference': self.project.getReference()})
finally:
if os.path.exists(self.compute_node_request_compute_node_simulator):
os.unlink(self.compute_node_request_compute_node_simulator)
......
......@@ -5,8 +5,8 @@ class TestSlapOSCoreComputeNodeUpdateFromDict(SlapOSTestCaseMixinWithAbort):
def afterSetUp(self):
SlapOSTestCaseMixinWithAbort.afterSetUp(self)
self.compute_node = self.portal.compute_node_module.template_compute_node\
.Base_createCloneDocument(batch_mode=1)
self.compute_node = self.portal.compute_node_module\
.newContent(portal_type="Compute Node")
self.compute_node.edit(
reference='TESTC-%s' % self.generateNewId(),
)
......
......@@ -373,7 +373,7 @@ class SlapTool(BaseTool):
security.declareProtected(Permissions.AccessContentsInformation,
'getSoftwareReleaseListFromSoftwareProduct')
def getSoftwareReleaseListFromSoftwareProduct(self,
def getSoftwareReleaseListFromSoftwareProduct(self, project_reference,
software_product_reference=None, software_release_url=None):
"""
Get the list of all published Software Releases related to one of either:
......@@ -384,12 +384,23 @@ class SlapTool(BaseTool):
If referenced Software Product does not exist, return empty list.
If referenced Software Release does not exist, raise.
"""
project_list = self.getPortalObject().portal_catalog.portal_catalog(
portal_type='Project',
reference=project_reference,
validation_state='validated',
limit=2
)
if len(project_list) != 1:
raise NotImplementedError("%i projects '%s'" % (len(project_list), project_reference))
project = project_list[0]
if software_product_reference is None:
assert(software_release_url is not None)
software_product_reference = self.getPortalObject().portal_catalog.unrestrictedSearchResults(
portal_type='Software Release',
portal_type='Software Product Release Variation',
parent__follow_up__uid=project.getUid(),
url_string=software_release_url
)[0].getObject().getAggregateValue().getReference()
)[0].getObject().getParentValue().getReference()
else:
# Don't accept both parameters
assert(software_release_url is None)
......@@ -397,13 +408,14 @@ class SlapTool(BaseTool):
software_product_list = self.getPortalObject().portal_catalog.unrestrictedSearchResults(
portal_type='Software Product',
reference=software_product_reference,
follow_up__uid=project.getUid(),
validation_state='published')
if len(software_product_list) is 0:
return dumps([])
if len(software_product_list) > 1:
raise NotImplementedError('Several Software Product with the same title.')
software_release_list = \
software_product_list[0].getObject().getAggregateRelatedValueList()
software_product_list[0].getObject().contentValues(portal_type='Software Product Release Variation')
def sortkey(software_release):
publication_date = software_release.getEffectiveDate()
......@@ -420,9 +432,7 @@ class SlapTool(BaseTool):
)
return dumps(
[software_release.getUrlString()
for software_release in software_release_list
if software_release.getValidationState() in \
['published', 'published_alive']])
for software_release in software_release_list])
security.declareProtected(Permissions.AccessContentsInformation,
'getHateoasUrl')
......@@ -508,20 +518,20 @@ class SlapTool(BaseTool):
return self._supplySupply(url, computer_id, state)
@convertToREST
def _requestComputeNode(self, compute_node_title):
def _requestComputeNode(self, compute_node_title, project_reference):
portal = self.getPortalObject()
person = portal.portal_membership.getAuthenticatedMember().getUserValue()
person.requestComputeNode(compute_node_title=compute_node_title)
person.requestComputeNode(compute_node_title=compute_node_title, project_reference=project_reference)
compute_node = ComputeNode(self.REQUEST.get('compute_node_reference').decode("UTF-8"))
return dumps(compute_node)
security.declareProtected(Permissions.AccessContentsInformation,
'requestComputer')
def requestComputer(self, computer_title):
def requestComputer(self, computer_title, project_reference):
"""
Request Compute Node
"""
return self._requestComputeNode(computer_title)
return self._requestComputeNode(computer_title, project_reference)
security.declareProtected(Permissions.AccessContentsInformation,
'buildingSoftwareRelease')
......@@ -615,7 +625,7 @@ class SlapTool(BaseTool):
def requestComputerPartition(self, computer_id=None,
computer_partition_id=None, software_release=None, software_type=None,
partition_reference=None, partition_parameter_xml=None,
filter_xml=None, state=None, shared_xml=_MARKER):
filter_xml=None, state=None, shared_xml=_MARKER, project_reference=None):
"""
Asynchronously requests creation of compute partition for assigned
parameters
......@@ -629,7 +639,8 @@ class SlapTool(BaseTool):
"""
return self._requestComputePartition(computer_id, computer_partition_id,
software_release, software_type, partition_reference,
shared_xml, partition_parameter_xml, filter_xml, state)
shared_xml, partition_parameter_xml, filter_xml, state,
project_reference)
security.declareProtected(Permissions.AccessContentsInformation,
'useComputer')
......@@ -926,7 +937,8 @@ class SlapTool(BaseTool):
@convertToREST
def _requestComputePartition(self, compute_node_id, compute_partition_id,
software_release, software_type, partition_reference,
shared_xml, partition_parameter_xml, filter_xml, state):
shared_xml, partition_parameter_xml, filter_xml, state,
project_reference):
"""
Asynchronously requests creation of compute partition for assigned
parameters
......@@ -964,7 +976,8 @@ class SlapTool(BaseTool):
instance_xml=castToStr(partition_parameter_kw),
shared=shared,
sla_xml=castToStr(filter_kw),
state=state)
state=state,
project_reference=project_reference)
portal = self.getPortalObject()
if compute_node_id and compute_partition_id:
......@@ -978,8 +991,48 @@ class SlapTool(BaseTool):
else:
# requested as root, so done by human
requester = portal.portal_membership.getAuthenticatedMember().getUserValue()
if project_reference is None:
# Compatibility with the slapos console client
# which does not send any project_reference parameter
# and always connect to a uniq url
# Try to guess the project reference automatically
project_list = portal.portal_catalog(portal_type='Project', limit=2)
if len(project_list) == 1:
# If the user only has access to one project
# we can easily suppose the request must be allocated here
kw['project_reference'] = project_list[0].getReference()
else:
release_variation_list = portal.portal_catalog(
portal_type='Software Product Release Variation',
url_string=software_release,
limit=2
)
if len(release_variation_list) == 1:
# If the user only has access to matching release variation
# we can easily suppose the request must be allocated on the same project
kw['project_reference'] = release_variation_list[0].getParentValue().getFollowUpReference()
# Finally, try to use the SLA parameter to guess where it could be
elif 'project_guid' in filter_kw:
kw['project_reference'] = filter_kw['project_guid']
elif 'computer_guid' in filter_kw:
computer_list = portal.portal_catalog(
portal_type=['Compute Node', 'Remote Node', 'Instance Node'],
limit=2
)
if len(computer_list == 1):
kw['project_reference'] = computer_list[0].getFollowUpReference()
elif 'network_guid' in filter_kw:
network_list = portal.portal_catalog(
portal_type='Computer Network',
limit=2
)
if len(network_list == 1):
kw['project_reference'] = network_list[0].getFollowUpReference()
key = '_'.join([requester.getRelativeUrl(), partition_reference])
last_data = requester.getLastData(key)
requested_software_instance = None
value = dict(
......@@ -989,7 +1042,7 @@ class SlapTool(BaseTool):
if last_data is not None and isinstance(last_data, type(value)):
requested_software_instance = self.restrictedTraverse(
last_data.get('request_instance'), None)
if last_data is None or not isinstance(last_data, type(value)) or \
last_data.get('hash') != value['hash'] or \
requested_software_instance is None:
......
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