Commit 87abc179 authored by Romain Courteaud's avatar Romain Courteaud

slapos_cloud: migrate Hosting Subscription to Instance Tree

parent 016b9a6f
......@@ -31,6 +31,10 @@ from Products.ERP5Security import SUPER_USER
from zExceptions import Unauthorized
from DateTime import DateTime
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from Acquisition import aq_base
# from erp5.portal_type import InstanceTree
def SoftwareInstance_bangAsSelf(self, relative_url=None, reference=None,
......@@ -92,3 +96,45 @@ def SoftwareInstance_renameAndRequestDestroy(self, REQUEST=None):
if (self.portal_slap._getLastData(key) != timestamp):
self.bang(bang_tree=True, comment="Instance was destroyed.")
self.portal_slap._storeLastData(key, str(int(self.getModificationDate())))
def HostingSubscription_checkInstanceTreeMigrationConsistency(self, fixit=False):
error_list = []
portal = self.getPortalObject()
# Do not use accessor, as backward compatibility will not be kept
if ((getattr(self, 'workflow_history', None) is not None) and
('hosting_subscription_workflow' in self.workflow_history)) or \
(self.getProperty('sla_xml', None) is not None) or \
([x for x in self.getCategoryList() if (x.startswith('predecessor/') or
x.startswith('successor/'))]):
error_list.append('Hosting Subscription must be migrated to an Instance Tree')
if fixit:
assert self.getPortalType() == 'Hosting Subscription'
hosting_subscription_id = self.getId()
hosting_subscription_relative_url = self.getRelativeUrl()
self.getParentValue()._delObject(hosting_subscription_id)
mod = __import__('erp5.portal_type', globals(), locals(), ['Instance Tree'])
klass = getattr(mod, 'Instance Tree')
self.__class__ = klass
# self.upgradeObjectClass(returnTrue, 'erp5.portal_type.Hosting Subscription', 'erp5.portal_type.Instance Tree', returnTrue)
self.portal_type = 'Instance Tree'
assert self.getPortalType() == 'Instance Tree'
if (getattr(self, 'workflow_history', None) is not None) and \
('hosting_subscription_workflow' in self.workflow_history):
self.workflow_history['instance_tree_workflow'] = self.workflow_history.pop('hosting_subscription_workflow')
portal.instance_tree_module._setOb(hosting_subscription_id, aq_base(self))
instance_tree = portal.instance_tree_module._getOb(hosting_subscription_id)
instance_tree.reindexObject()
UnrestrictedMethod(instance_tree.updateRelatedContent)(hosting_subscription_relative_url, instance_tree.getRelativeUrl())
# raise NotImplementedError('couscous')
return error_list
......@@ -22,6 +22,9 @@
<portal_type id="Email">
<item>SlaposEmailConstraint</item>
</portal_type>
<portal_type id="Hosting Subscription">
<item>HostingSubscriptionUpgradeConstraint</item>
</portal_type>
<portal_type id="Instance Tree">
<item>InstanceTree</item>
<item>SlaposInstanceTreeConstraint</item>
......
......@@ -91,8 +91,6 @@
<string>description</string>
<string>reference</string>
<string>short_title</string>
<string>text_content</string>
<string>sla_xml</string>
</tuple>
</value>
</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>HostingSubscriptionUpgradeConstraint</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>instance_tree_migration_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>HostingSubscription_checkInstanceTreeMigrationConsistency</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>
<?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/post_upgrade</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>instance_tree_migration_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>AlarmTool_checkInstanceTreeMigrationConsistency</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()
result_list = []
migration_kw = {
'portal_type': 'Hosting Subscription',
'slap_state': '%'
}
non_migrated_instance = portal.portal_catalog(limit=1, **migration_kw)
if len(non_migrated_instance) == 1:
result_list.append("all X needs updates %s" % non_migrated_instance[0].getRelativeUrl())
if fixit:
portal.portal_catalog.searchAndActivate(
activate_kw=dict(priority=5,
tag=script.getId(),
after_method_id=('immediateReindexObject',
'recursiveImmediateReindexObject')),
method_id='fixConsistency',
**migration_kw)
return result_list
<?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=False</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>AlarmTool_checkInstanceTreeMigrationConsistency</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ExternalMethod" module="Products.ExternalMethod.ExternalMethod"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_function</string> </key>
<value> <string>HostingSubscription_checkInstanceTreeMigrationConsistency</string> </value>
</item>
<item>
<key> <string>_module</string> </key>
<value> <string>SlapOSCloud</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>HostingSubscription_checkInstanceTreeMigrationConsistency</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -5,6 +5,7 @@
#
##############################################################################
from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixin
from DateTime import DateTime
def getMessageList(instance):
......@@ -60,3 +61,84 @@ class TestSlapOSCloudUpgrader(SlapOSTestCaseMixin):
def test_upgrade_instance_tree_predecessor(self):
return self.check_upgrade_instance_predecessor('Instance Tree')
def test_upgrade_hosting_subscription_to_instance_tree(self):
migration_message = 'Hosting Subscription must be migrated to an Instance Tree'
hosting_subscription_module = self.portal.getDefaultModule('Hosting Subscription')
hosting_subscription_nothing_to_migrate = hosting_subscription_module.newContent(
portal_type='Hosting Subscription'
)
hosting_subscription_to_migrate = hosting_subscription_module.newContent(
portal_type='Hosting Subscription',
sla_xml='foo',
bar='foo3',
category_list=['successor/foo1', 'predecessor/foo2']
)
# Create fake workflow history
creation_date = DateTime('2011/11/15 11:11')
modification_date = DateTime('2012/11/15 11:11')
hosting_subscription_to_migrate.workflow_history['edit_workflow'] = [{
'comment':'Fake history',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'state': 'current',
'time': creation_date,
'action': 'foo_action'
}]
hosting_subscription_to_migrate.workflow_history['hosting_subscription_workflow'] = [{
'comment':'Fake history',
'error_message': '',
'actor': 'ERP5TypeTestCase',
'validation_state': 'validated',
'time': modification_date,
'action': 'validate'
}]
software_instance = self.portal.software_instance_module.newContent(
portal_type='Software Instance',
aggregate_value=hosting_subscription_to_migrate
)
hosting_subscription_to_migrate_id = hosting_subscription_to_migrate.getId()
hosting_subscription_to_migrate_uid = hosting_subscription_to_migrate.getUid()
self.tic()
# Nothing to migrate
self.assertFalse(migration_message in getMessageList(hosting_subscription_nothing_to_migrate))
# To migrate
self.assertTrue(migration_message in getMessageList(hosting_subscription_to_migrate))
hosting_subscription_to_migrate.fixConsistency()
self.tic()
instance_tree_module = self.portal.getDefaultModule('Instance Tree')
migrated_instance_tree = instance_tree_module.restrictedTraverse(hosting_subscription_to_migrate_id)
self.assertEqual('Instance Tree',
migrated_instance_tree.getPortalType())
self.assertEqual(self.portal.instance_tree_module,
migrated_instance_tree.getParentValue())
self.assertEqual(hosting_subscription_to_migrate_id,
migrated_instance_tree.getId())
self.assertEqual(hosting_subscription_to_migrate_uid,
migrated_instance_tree.getUid())
self.assertEqual('foo',
migrated_instance_tree.getSlaXml())
self.assertEqual('foo1',
migrated_instance_tree.getSuccessor())
self.assertEqual('foo2',
migrated_instance_tree.getPredecessor())
self.assertEqual('foo3',
migrated_instance_tree.getProperty('bar'))
self.assertEqual('validated',
migrated_instance_tree.getValidationState())
self.assertEqual(creation_date,
migrated_instance_tree.getCreationDate())
# self.assertEqual(modification_date,
# migrated_instance_tree.getModificationDate())
self.assertFalse('hosting_subscription_workflow' in migrated_instance_tree.workflow_history)
self.assertFalse(migration_message in getMessageList(migrated_instance_tree))
self.assertEqual(migrated_instance_tree.getRelativeUrl(),
software_instance.getAggregate())
......@@ -9,6 +9,7 @@ Computer | SlaposCapacity
Computer | SlaposComputerConstraint
Computer | Url
Email | SlaposEmailConstraint
Hosting Subscription | HostingSubscriptionUpgradeConstraint
Instance Tree | InstanceTree
Instance Tree | SlaposInstanceTreeConstraint
Instance Tree | SoftwareInstance
......
......@@ -4,6 +4,7 @@ SlaposComputerPartitionConstraint
SlaposInstanceTreeConstraint
SlaveInstanceConstraint
InternetProtocolAddress
HostingSubscriptionUpgradeConstraint
ComputerPartition
SoftwareInstance
SoftwareInstanceUpgradeConstraint
......
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