Commit cc426ec7 authored by Rafael Monnerat's avatar Rafael Monnerat

slapos_cloud: Add constraint to prevent duplicated references on some portal types

   It is essential that reference is Unique, since it is widely used for security and SLA.

   This replaces one alarm present on slapos_administration to detect it, now we may rely on checkConsistency checks.
parent fbfd1b35
......@@ -9,6 +9,7 @@
<item>ComputeNodeSlapOSMetadata</item>
<item>ComputerUpgradeConstraint</item>
<item>ERP5User</item>
<item>SlapOSReferenceConstraint</item>
<item>SlaposCapacity</item>
<item>SlaposComputeNodeConstraint</item>
<item>Url</item>
......@@ -36,6 +37,7 @@
<portal_type id="Instance Tree">
<item>HostingSubscriptionUpgradeConstraint</item>
<item>InstanceTree</item>
<item>SlapOSReferenceConstraint</item>
<item>SlaposInstanceTreeConstraint</item>
<item>SoftwareInstance</item>
<item>SoftwareInstanceUpgradeConstraint</item>
......@@ -49,6 +51,7 @@
<portal_type id="Slave Instance">
<item>InstanceTree</item>
<item>Reference</item>
<item>SlapOSReferenceConstraint</item>
<item>SlaveInstanceConstraint</item>
<item>SoftwareInstance</item>
<item>SoftwareInstanceDuplicationConstraint</item>
......@@ -57,6 +60,7 @@
<item>VariationRange</item>
</portal_type>
<portal_type id="Software Installation">
<item>SlapOSReferenceConstraint</item>
<item>Url</item>
<item>VariationRange</item>
</portal_type>
......@@ -64,6 +68,7 @@
<item>ERP5User</item>
<item>InstanceTree</item>
<item>Reference</item>
<item>SlapOSReferenceConstraint</item>
<item>SoftwareInstance</item>
<item>SoftwareInstanceConstraint</item>
<item>SoftwareInstanceDuplicationConstraint</item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Property Sheet" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SlapOSReferenceConstraint</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Property Sheet</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Length" module="BTrees.Length"/>
</pickle>
<pickle> <int>0</int> </pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Script Constraint" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>constraint_type/default</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>check_duplicate_constraint</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Script Constraint</string> </value>
</item>
<item>
<key> <string>script_id</string> </key>
<value> <string>Base_checkDuplicatedReference</string> </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>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
portal = context.getPortalObject()
error_list = []
reference = context.getReference()
result = portal.portal_catalog(reference=reference,
portal_type=context.getPortalType(), limit=2)
if len(result) > 1 or \
(len(result) == 1 and result[0].getUid() != context.getUid()):
error_list.append("%s (%s) has duplicated reference." % (
context.getRelativeUrl(), context.getReference()))
return error_list
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>fixit, active_process</string> </value>
<value> <string>fixit=False</string> </value>
</item>
<item>
<key> <string>id</string> </key>
......
......@@ -237,9 +237,11 @@ class TestSlapOSSoftwareInstanceConstraint(TestSlapOSConstraintMixin):
def test_successor_related(self):
software_instance2 = self.portal.software_instance_module.newContent(
portal_type='Software Instance')
portal_type='Software Instance',
reference="TESTSOFTINST-%s" % self.generateNewId())
software_instance3 = self.portal.software_instance_module.newContent(
portal_type='Software Instance')
portal_type='Software Instance',
reference="TESTSOFTINST-%s" % self.generateNewId())
# fetch basic list of consistency messages
current_message_list = self.getMessageList(self.software_instance)
......@@ -376,9 +378,11 @@ class TestSlapOSSlaveInstanceConstraint(TestSlapOSConstraintMixin):
def test_successor_related(self):
software_instance2 = self.portal.software_instance_module.newContent(
portal_type='Slave Instance')
portal_type='Slave Instance',
reference="TESTSOFTINST-%s" % self.generateNewId())
software_instance3 = self.portal.software_instance_module.newContent(
portal_type='Slave Instance')
portal_type='Slave Instance',
reference="TESTSOFTINST-%s" % self.generateNewId())
# fetch basic list of consistency messages
current_message_list = self.getMessageList(self.software_instance)
......
......@@ -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>testSlapOSCloudConstraint</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>
......
......@@ -3,6 +3,7 @@ Assignment | SlaposAssignmentConstraint
Compute Node | ComputeNodeSlapOSMetadata
Compute Node | ComputerUpgradeConstraint
Compute Node | ERP5User
Compute Node | SlapOSReferenceConstraint
Compute Node | SlaposCapacity
Compute Node | SlaposComputeNodeConstraint
Compute Node | Url
......@@ -16,6 +17,7 @@ Email | SlaposEmailConstraint
Hosting Subscription | HostingSubscriptionUpgradeConstraint
Instance Tree | HostingSubscriptionUpgradeConstraint
Instance Tree | InstanceTree
Instance Tree | SlapOSReferenceConstraint
Instance Tree | SlaposInstanceTreeConstraint
Instance Tree | SoftwareInstance
Instance Tree | SoftwareInstanceUpgradeConstraint
......@@ -25,17 +27,20 @@ Instance Tree | VariationRange
Person | SlaposPersonConstraint
Slave Instance | InstanceTree
Slave Instance | Reference
Slave Instance | SlapOSReferenceConstraint
Slave Instance | SlaveInstanceConstraint
Slave Instance | SoftwareInstance
Slave Instance | SoftwareInstanceDuplicationConstraint
Slave Instance | TextDocument
Slave Instance | Url
Slave Instance | VariationRange
Software Installation | SlapOSReferenceConstraint
Software Installation | Url
Software Installation | VariationRange
Software Instance | ERP5User
Software Instance | InstanceTree
Software Instance | Reference
Software Instance | SlapOSReferenceConstraint
Software Instance | SoftwareInstance
Software Instance | SoftwareInstanceConstraint
Software Instance | SoftwareInstanceDuplicationConstraint
......
......@@ -17,4 +17,5 @@ SlaposPersonConstraint
SlaposAssignmentConstraint
SlaposEmailConstraint
SlaposComputeNodeConstraint
ComputeNodeSlapOSMetadata
\ No newline at end of file
ComputeNodeSlapOSMetadata
SlapOSReferenceConstraint
\ No newline at end of file
active_process = context.newActiveProcess().getRelativeUrl()
context.getPortalObject().portal_catalog.searchAndActivate(
method_id='Base_checkDuplicatedReference',
method_kw=dict(fixit=fixit, active_process=active_process),
activate_kw=dict(tag=tag, priority=5),
portal_type=["Instance Tree", "Compute Node", "Software Instance", "Slave Instance", "Software Installation"],
validation_state="validated")
return
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>tag, fixit, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Alarm_searchDuplicatedObjectReference</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from Products.CMFActivity.ActiveResult import ActiveResult
portal = context.getPortalObject()
reference = context.getReference()
active_process = portal.restrictedTraverse(active_process)
result = portal.portal_catalog(portal_type=context.getPortalType(),
reference=reference,
limit=2)
if len(result) != 1:
active_process.postResult(ActiveResult(
summary="%s %s has duplication" % (context.getRelativeUrl(), context.getReference()),
severity=100,
detail=""))
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