Commit 34bf4cba authored by Rafael Monnerat's avatar Rafael Monnerat

New constraints from Admin alarms

See merge request !420
parents 1bf8c5a0 015f2b24
......@@ -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>
......@@ -49,13 +50,16 @@
<portal_type id="Slave Instance">
<item>InstanceTree</item>
<item>Reference</item>
<item>SlapOSReferenceConstraint</item>
<item>SlaveInstanceConstraint</item>
<item>SoftwareInstance</item>
<item>SoftwareInstanceDuplicationConstraint</item>
<item>TextDocument</item>
<item>Url</item>
<item>VariationRange</item>
</portal_type>
<portal_type id="Software Installation">
<item>SlapOSReferenceConstraint</item>
<item>Url</item>
<item>VariationRange</item>
</portal_type>
......@@ -63,8 +67,10 @@
<item>ERP5User</item>
<item>InstanceTree</item>
<item>Reference</item>
<item>SlapOSReferenceConstraint</item>
<item>SoftwareInstance</item>
<item>SoftwareInstanceConstraint</item>
<item>SoftwareInstanceDuplicationConstraint</item>
<item>SoftwareInstanceUpgradeConstraint</item>
<item>TextDocument</item>
<item>Url</item>
......
......@@ -2,54 +2,65 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Alarm" module="erp5.portal_type"/>
<global name="Property Sheet" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_searchDuplicatedSoftwareInstance</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Search for Duplicated Software Instance on a Single Instance Tree</string> </value>
<key> <string>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>0</int> </value>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>slapos_check_duplicated_software_instance</string> </value>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>periodicity_start_date</string> </key>
<key> <string>description</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>433814400.0</float>
<string>GMT</string>
</tuple>
</state>
</object>
<none/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Alarm</string> </value>
<key> <string>id</string> </key>
<value> <string>SlapOSReferenceConstraint</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Search Duplicated Software Instances</string> </value>
<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>
......@@ -34,7 +34,7 @@
</item>
<item>
<key> <string>filter_parameter</string> </key>
<value> <string>python: {\'portal_type\': (object.getPortalType(), \'Person\'), \'reference\': object.getReference()}</string> </value>
<value> <string>python: {\'portal_type\': (object.getPortalType(), ), \'reference\': object.getReference()}</string> </value>
</item>
<item>
<key> <string>id</string> </key>
......
<?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>SoftwareInstanceDuplicationConstraint</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>duplication_instance_on_instance_tree_constraint_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>SoftwareInstance_checkDuplicationOnInstanceTreeConsistency</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>
if context.getSlapState() == "destroy_requested":
return []
instance_tree = context.getSpecialiseValue(portal_type="Instance Tree")
error_list = []
if instance_tree:
title = context.getTitle()
for instance in instance_tree.getSpecialiseRelatedValueList(
portal_type=["Slave Instance", "Software Instance"]):
if instance.getSlapState() == "destroy_requested" or\
instance.getUid() == context.getUid():
continue
if instance.getTitle() == title:
error_list.append("%s is duplicated with %s " % (
title, instance.getRelativeUrl()))
return error_list
......@@ -50,11 +50,11 @@
</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>
<value> <string>Base_checkDuplicatedReference</string> </value>
<value> <string>SoftwareInstance_checkDuplicationOnInstanceTreeConsistency</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -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)
......@@ -546,37 +550,69 @@ class TestSlapOSComputeNodeConstraint(TestSlapOSConstraintMixin):
consistency_message = 'Title must be defined'
self.assertTrue(consistency_message in self.getMessageList(compute_node))
compute_node.setTitle(self.generateNewId())
self.assertFalse(consistency_message in self.getMessageList(compute_node))
def test_reference_not_empty(self):
compute_node = self.portal.compute_node_module.newContent(portal_type='Compute Node')
consistency_message = 'Reference must be defined'
self.assertTrue(consistency_message in self.getMessageList(compute_node))
class TestSlapOSReferenceConstraint(TestSlapOSConstraintMixin):
compute_node.setReference(self.generateNewId())
def test_reference_not_empty_compute_node(self):
self._test_reference_not_empty(
self.portal.compute_node_module.newContent(portal_type='Compute Node'))
self.assertFalse(consistency_message in self.getMessageList(compute_node))
def test_reference_not_empty_software_instance(self):
self._test_reference_not_empty(
self.portal.software_instance_module.newContent(portal_type='Software Instance'))
def test_reference_unique(self):
reference = self.generateNewId()
reference_2 = self.generateNewId()
compute_node = self.portal.compute_node_module.newContent(portal_type='Compute Node',
reference=reference)
compute_node_2 = self.portal.compute_node_module.newContent(portal_type='Compute Node',
reference=reference)
consistency_message = 'Reference must be unique'
def test_reference_not_empty_slave_instance(self):
self._test_reference_not_empty(
self.portal.software_instance_module.newContent(portal_type='Slave Instance'))
def test_reference_not_empty_software_installation(self):
self._test_reference_not_empty(
self.portal.software_installation_module.newContent(portal_type='Software Installation'))
def _test_reference_not_empty(self, document):
consistency_message = 'Reference must be defined'
self.assertIn(consistency_message, self.getMessageList(document))
document.setReference(self.generateNewId())
self.assertNotIn(consistency_message, self.getMessageList(document))
def test_reference_unique_compute_node(self):
module = self.portal.compute_node_module
self._test_reference_unique(
module.newContent(portal_type='Compute Node', reference=self.generateNewId()),
module.newContent(portal_type='Compute Node', reference=self.generateNewId()))
def test_reference_unique_software_instance(self):
module = self.portal.software_instance_module
self._test_reference_unique(
module.newContent(portal_type='Software Instance', reference=self.generateNewId()),
module.newContent(portal_type='Software Instance', reference=self.generateNewId()))
def test_reference_unique_slave_instance(self):
module = self.portal.software_instance_module
self._test_reference_unique(
module.newContent(portal_type='Slave Instance', reference=self.generateNewId()),
module.newContent(portal_type='Slave Instance', reference=self.generateNewId()))
def test_reference_unique_software_installation(self):
module = self.portal.software_installation_module
self._test_reference_unique(
module.newContent(portal_type='Software Installation', reference=self.generateNewId()),
module.newContent(portal_type='Software Installation', reference=self.generateNewId()))
def _test_reference_unique(self, documentA, documentB):
consistency_message = 'Reference must be unique'
self.tic()
self.assertTrue(consistency_message in self.getMessageList(compute_node))
self.assertTrue(consistency_message in self.getMessageList(compute_node_2))
self.assertNotIn(consistency_message, self.getMessageList(documentA))
self.assertNotIn(consistency_message, self.getMessageList(documentB))
compute_node_2.setReference(reference_2)
documentB.setReference(documentA.getReference())
self.tic()
self.assertFalse(consistency_message in self.getMessageList(compute_node))
self.assertFalse(consistency_message in self.getMessageList(compute_node_2))
self.assertEqual(documentB.getReference(), documentA.getReference())
self.assertIn(consistency_message, self.getMessageList(documentA))
self.assertIn(consistency_message, self.getMessageList(documentB))
......@@ -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
......@@ -25,18 +26,23 @@ 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
Software Instance | SoftwareInstanceUpgradeConstraint
Software Instance | TextDocument
Software Instance | Url
......
......@@ -10,10 +10,12 @@ ComputerPartitionUpgradeConstraint
ComputePartition
SoftwareInstance
SoftwareInstanceUpgradeConstraint
SoftwareInstanceDuplicationConstraint
InstanceTree
SlaposCapacity
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>
active_process = context.newActiveProcess().getRelativeUrl()
context.getPortalObject().portal_catalog.searchAndActivate(
method_id='InstanceTree_checkDuplicatedInstance',
method_kw=dict(fixit=fixit, active_process=active_process),
activate_kw=dict(tag=tag, priority=5),
portal_type="Instance Tree",
validation_state="validated")
<?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_searchDuplicatedSoftwareInstance</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=""))
from Products.CMFActivity.ActiveResult import ActiveResult
portal = context.getPortalObject()
software_instance_list = context.getSpecialiseRelatedValueList(
portal_type=["Slave Instance", "Software Instance"])
if len(software_instance_list) == 1:
return
title_dict = {}
active_process = portal.restrictedTraverse(active_process)
for software_instance in software_instance_list:
if software_instance.getSlapState() == "destroy_requested":
continue
title = software_instance.getTitle()
if title in title_dict:
title_dict[title].append(software_instance.getObject())
else:
title_dict[title] = [software_instance.getObject()]
for title in title_dict:
if len(title_dict[title]) > 1:
if fixit:
for software_instance in title_dict[title]:
if len(software_instance.getAggregate([])) == 0:
active_process.postResult(ActiveResult(
summary="Fixing %s which duplication and is not allocated (%s)" \
% (software_instance.getRelativeUrl(), context.getRelativeUrl()),
severity=0,
detail=""))
software_instance.activate().SoftwareInstance_destroyAsSelf()
else:
active_process.postResult(ActiveResult(
summary="%s has duplication" % context.getRelativeUrl(),
severity=100,
detail="%s has duplication on %s (%s)" % (context.getRelativeUrl(), title, len(title_dict[title]))))
<?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>fixit, active_process</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>InstanceTree_checkDuplicatedInstance</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
notification_message_module/slapos_erp5_credential_recovery_password_expiration_link_en_001
notification_message_module/slapos_erp5_credential_recovery_password_expiration_link_en_001/**
portal_alarms/open_bugs_alarm
portal_alarms/slapos_check_duplicated_software_instance
portal_alarms/slapos_check_security_uid
portal_alarms/slapos_check_stored_broken_state
portal_alarms/slapos_erp5_cleanup_active_process
......
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