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 @@ ...@@ -9,6 +9,7 @@
<item>ComputeNodeSlapOSMetadata</item> <item>ComputeNodeSlapOSMetadata</item>
<item>ComputerUpgradeConstraint</item> <item>ComputerUpgradeConstraint</item>
<item>ERP5User</item> <item>ERP5User</item>
<item>SlapOSReferenceConstraint</item>
<item>SlaposCapacity</item> <item>SlaposCapacity</item>
<item>SlaposComputeNodeConstraint</item> <item>SlaposComputeNodeConstraint</item>
<item>Url</item> <item>Url</item>
...@@ -36,6 +37,7 @@ ...@@ -36,6 +37,7 @@
<portal_type id="Instance Tree"> <portal_type id="Instance Tree">
<item>HostingSubscriptionUpgradeConstraint</item> <item>HostingSubscriptionUpgradeConstraint</item>
<item>InstanceTree</item> <item>InstanceTree</item>
<item>SlapOSReferenceConstraint</item>
<item>SlaposInstanceTreeConstraint</item> <item>SlaposInstanceTreeConstraint</item>
<item>SoftwareInstance</item> <item>SoftwareInstance</item>
<item>SoftwareInstanceUpgradeConstraint</item> <item>SoftwareInstanceUpgradeConstraint</item>
...@@ -49,6 +51,7 @@ ...@@ -49,6 +51,7 @@
<portal_type id="Slave Instance"> <portal_type id="Slave Instance">
<item>InstanceTree</item> <item>InstanceTree</item>
<item>Reference</item> <item>Reference</item>
<item>SlapOSReferenceConstraint</item>
<item>SlaveInstanceConstraint</item> <item>SlaveInstanceConstraint</item>
<item>SoftwareInstance</item> <item>SoftwareInstance</item>
<item>SoftwareInstanceDuplicationConstraint</item> <item>SoftwareInstanceDuplicationConstraint</item>
...@@ -57,6 +60,7 @@ ...@@ -57,6 +60,7 @@
<item>VariationRange</item> <item>VariationRange</item>
</portal_type> </portal_type>
<portal_type id="Software Installation"> <portal_type id="Software Installation">
<item>SlapOSReferenceConstraint</item>
<item>Url</item> <item>Url</item>
<item>VariationRange</item> <item>VariationRange</item>
</portal_type> </portal_type>
...@@ -64,6 +68,7 @@ ...@@ -64,6 +68,7 @@
<item>ERP5User</item> <item>ERP5User</item>
<item>InstanceTree</item> <item>InstanceTree</item>
<item>Reference</item> <item>Reference</item>
<item>SlapOSReferenceConstraint</item>
<item>SoftwareInstance</item> <item>SoftwareInstance</item>
<item>SoftwareInstanceConstraint</item> <item>SoftwareInstanceConstraint</item>
<item>SoftwareInstanceDuplicationConstraint</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 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>fixit, active_process</string> </value> <value> <string>fixit=False</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
...@@ -237,9 +237,11 @@ class TestSlapOSSoftwareInstanceConstraint(TestSlapOSConstraintMixin): ...@@ -237,9 +237,11 @@ class TestSlapOSSoftwareInstanceConstraint(TestSlapOSConstraintMixin):
def test_successor_related(self): def test_successor_related(self):
software_instance2 = self.portal.software_instance_module.newContent( 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( 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 # fetch basic list of consistency messages
current_message_list = self.getMessageList(self.software_instance) current_message_list = self.getMessageList(self.software_instance)
...@@ -376,9 +378,11 @@ class TestSlapOSSlaveInstanceConstraint(TestSlapOSConstraintMixin): ...@@ -376,9 +378,11 @@ class TestSlapOSSlaveInstanceConstraint(TestSlapOSConstraintMixin):
def test_successor_related(self): def test_successor_related(self):
software_instance2 = self.portal.software_instance_module.newContent( 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( 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 # fetch basic list of consistency messages
current_message_list = self.getMessageList(self.software_instance) current_message_list = self.getMessageList(self.software_instance)
......
...@@ -6,12 +6,6 @@ ...@@ -6,12 +6,6 @@
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item> <item>
<key> <string>default_reference</string> </key> <key> <string>default_reference</string> </key>
<value> <string>testSlapOSCloudConstraint</string> </value> <value> <string>testSlapOSCloudConstraint</string> </value>
...@@ -55,28 +49,13 @@ ...@@ -55,28 +49,13 @@
<item> <item>
<key> <string>workflow_history</string> </key> <key> <string>workflow_history</string> </key>
<value> <value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent> <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
<record id="2" aka="AAAAAAAAAAI="> <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> <pickle>
<global name="PersistentMapping" module="Persistence.mapping"/> <global name="PersistentMapping" module="Persistence.mapping"/>
</pickle> </pickle>
...@@ -89,7 +68,7 @@ ...@@ -89,7 +68,7 @@
<item> <item>
<key> <string>component_validation_workflow</string> </key> <key> <string>component_validation_workflow</string> </key>
<value> <value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent> <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value> </value>
</item> </item>
</dictionary> </dictionary>
...@@ -98,7 +77,7 @@ ...@@ -98,7 +77,7 @@
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
<record id="4" aka="AAAAAAAAAAQ="> <record id="3" aka="AAAAAAAAAAM=">
<pickle> <pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/> <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle> </pickle>
......
...@@ -3,6 +3,7 @@ Assignment | SlaposAssignmentConstraint ...@@ -3,6 +3,7 @@ Assignment | SlaposAssignmentConstraint
Compute Node | ComputeNodeSlapOSMetadata Compute Node | ComputeNodeSlapOSMetadata
Compute Node | ComputerUpgradeConstraint Compute Node | ComputerUpgradeConstraint
Compute Node | ERP5User Compute Node | ERP5User
Compute Node | SlapOSReferenceConstraint
Compute Node | SlaposCapacity Compute Node | SlaposCapacity
Compute Node | SlaposComputeNodeConstraint Compute Node | SlaposComputeNodeConstraint
Compute Node | Url Compute Node | Url
...@@ -16,6 +17,7 @@ Email | SlaposEmailConstraint ...@@ -16,6 +17,7 @@ Email | SlaposEmailConstraint
Hosting Subscription | HostingSubscriptionUpgradeConstraint Hosting Subscription | HostingSubscriptionUpgradeConstraint
Instance Tree | HostingSubscriptionUpgradeConstraint Instance Tree | HostingSubscriptionUpgradeConstraint
Instance Tree | InstanceTree Instance Tree | InstanceTree
Instance Tree | SlapOSReferenceConstraint
Instance Tree | SlaposInstanceTreeConstraint Instance Tree | SlaposInstanceTreeConstraint
Instance Tree | SoftwareInstance Instance Tree | SoftwareInstance
Instance Tree | SoftwareInstanceUpgradeConstraint Instance Tree | SoftwareInstanceUpgradeConstraint
...@@ -25,17 +27,20 @@ Instance Tree | VariationRange ...@@ -25,17 +27,20 @@ Instance Tree | VariationRange
Person | SlaposPersonConstraint Person | SlaposPersonConstraint
Slave Instance | InstanceTree Slave Instance | InstanceTree
Slave Instance | Reference Slave Instance | Reference
Slave Instance | SlapOSReferenceConstraint
Slave Instance | SlaveInstanceConstraint Slave Instance | SlaveInstanceConstraint
Slave Instance | SoftwareInstance Slave Instance | SoftwareInstance
Slave Instance | SoftwareInstanceDuplicationConstraint Slave Instance | SoftwareInstanceDuplicationConstraint
Slave Instance | TextDocument Slave Instance | TextDocument
Slave Instance | Url Slave Instance | Url
Slave Instance | VariationRange Slave Instance | VariationRange
Software Installation | SlapOSReferenceConstraint
Software Installation | Url Software Installation | Url
Software Installation | VariationRange Software Installation | VariationRange
Software Instance | ERP5User Software Instance | ERP5User
Software Instance | InstanceTree Software Instance | InstanceTree
Software Instance | Reference Software Instance | Reference
Software Instance | SlapOSReferenceConstraint
Software Instance | SoftwareInstance Software Instance | SoftwareInstance
Software Instance | SoftwareInstanceConstraint Software Instance | SoftwareInstanceConstraint
Software Instance | SoftwareInstanceDuplicationConstraint Software Instance | SoftwareInstanceDuplicationConstraint
......
...@@ -18,3 +18,4 @@ SlaposAssignmentConstraint ...@@ -18,3 +18,4 @@ SlaposAssignmentConstraint
SlaposEmailConstraint SlaposEmailConstraint
SlaposComputeNodeConstraint SlaposComputeNodeConstraint
ComputeNodeSlapOSMetadata 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