Commit 2e902287 authored by Romain Courteaud's avatar Romain Courteaud

slapos_upgrader:

* WIP migration scripts
* migrate compute node
* do not skip some migration
* migrate more properties on compute node
* migrate software installation
* migrate compute already linked to a project
* trigger instance tree migration
* migrate more instance trees
* migrate Instance Tree, Software/Slave Instance
* migrate instance tree
* do not create not needed activities
* migrate instance tree linked to an existing project
* migrate existing subscription requests/projects
* allow to run the migration multiple time
* move an instance to the same virtual master than his main compute node
* if all instances are linked to the same project, move the computer to that project
* migrate computer network
* move to personal if no instance allocated
* partially destroyed instanc ewill move to personal
  Unallocated instance will use remote note
* force migration to remaining compute nodes
* break network link if not consistent
* create Remote Node and Remote Instances
* reduce concurrency on instance tree creation
* try to reduce conflict
* some sla xml seems broken
* instances do not always have a predecessor
* it seems activity is also triggered on already migrated instance
* some instances were manually invalidated...
* do not go too slowly
* generate a graph showing the virtual master relation
* another report
* prepare migrating Instance Tree to a remote node
* change report output
* fixup instance virtual master migration
  do not forget to also move the successor to the new virtual master
* do not fail if already migrated
* create Software Product (and its variations)
* create Instance Node
* create allocation supplies
parent a182e65b
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
return context.getTypeBasedMethod('triggerObjectMigrationToRemoteVirtualMaster')(project_relative_url)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>project_relative_url, REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_activateObjectMigrationToRemoteVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
return context.getTypeBasedMethod('triggerObjectMigrationToVirtualMaster')(project_relative_url)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>project_relative_url, REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_activateObjectMigrationToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
container = context.getParentValue()
container.manage_delObjects(ids=[context.getId()])
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_deleteProcessedDocumentDuringPurge</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# https://playground.diagram.codes/d/graph
portal = context.getPortalObject()
print "ARROWS"
print ""
project_dict = {}
remote_project_dict = {}
group_by_list = ["follow_up__uid"]
sql_result_list = context.getPortalObject().portal_catalog(
select_list=group_by_list+['count(*)'],
portal_type="Instance Tree",
slap_state=["start_requested", "stop_requested"],
group_by=group_by_list
)
for sql_result in sql_result_list:
project_dict[sql_result.getFollowUpUid()] = {
'title': '%s (%s)' % (sql_result.getFollowUpTitle(), sql_result['count(*)']),
'remote_uid_list': []
}
for sql_remote in context.getPortalObject().portal_catalog(
portal_type="Remote Node",
follow_up__uid=sql_result.getFollowUpUid()
):
project_dict[sql_result.getFollowUpUid()]['remote_uid_list'].append(sql_remote.getDestinationProjectUid())
remote_project_dict[sql_remote.getDestinationProjectUid()] = True
project_dict[sql_result.getFollowUpUid()]['remote_uid_list'] = sorted(project_dict[sql_result.getFollowUpUid()]['remote_uid_list'])
# Calculate all the nodes
# Remote projects will be standalone
# Other project will be grouped by their remote
display_dict = {}
for project_uid, project_value_dict in project_dict.items():
if project_uid in remote_project_dict:
display_dict[project_uid] = project_value_dict
else:
remote_key = 'remote_%s' % ''.join(sorted([str(x) for x in project_value_dict['remote_uid_list']])) or 'couscous'
if remote_key not in display_dict:
display_dict[remote_key] = {
'remote_uid_list': project_value_dict['remote_uid_list'],
'title': project_value_dict['title']
}
else:
display_dict[remote_key]['title'] = '%s\n%s' % (display_dict[remote_key]['title'], project_value_dict['title'])
for display_key, display_value in display_dict.items():
print '"%s" as %s' % (display_value['title'], display_key)
print ''
for display_key, display_value in display_dict.items():
has_remote = False
for remote_uid in display_value['remote_uid_list']:
if remote_uid in display_dict:
# only not destroyed links
has_remote = True
print '%s->%s' % (display_key, remote_uid)
if (not has_remote) and (display_key not in remote_project_dict):
print '%s->%s' % (display_key, display_key)
print ''
return printed
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_reportVirtualMasterMigration</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
group_by_list = ["url_string", "source_reference", "follow_up_title"]
sql_result_list = context.getPortalObject().portal_catalog(
select_list=group_by_list+['count(*)'],
portal_type="Instance Tree",
title="_remote_%",
#url_string="https://lab.nexedi.com/nexedi/slapos/%",
slap_state=["start_requested", "stop_requested"],
group_by=group_by_list,
#sort_on=[['count(*)', 'DESC']]
)
project_soft_dict = {}
soft_proj_dict = {}
for sql_result in sql_result_list:
soft = sql_result['url_string'].split('/')[-2] + ' <i>' + sql_result['source_reference'] + '</i>'
project = sql_result['follow_up_title']
"""
if project not in project_soft_dict:
project_soft_dict[project] = {}
if soft not in project_soft_dict[project]:
project_soft_dict[project][soft] = 0
project_soft_dict[project][soft] = project_soft_dict[project][soft] + int(sql_result['count(*)'])
"""
if soft not in soft_proj_dict:
soft_proj_dict[soft] = {'project_list': [], 'count': 0}
soft_proj_dict[soft]['project_list'].append(project)
soft_proj_dict[soft]['count'] = soft_proj_dict[soft]['count'] + int(sql_result['count(*)'])
print '<ul>'
"""
for project, soft_dict in project_soft_dict.items():
print '<li><p>%s</p><ul>' % project
for soft, count in soft_dict.items():
print '<li><p>%s <b>%i</b></p></li>' % (soft, count)
print '</ul></li>'
"""
ordered_list = soft_proj_dict.items()
ordered_list.sort()
for soft, info_dict in ordered_list:
print '<li><p>%s <b>%i</b> %s</p>' % (soft, info_dict['count'], str(list(set(info_dict['project_list']))))
"""
for proj in list(set(info_dict['project_list'])):
print '<li><p>%s</p></li>' % (proj)
"""
print '</li>'
print '</ul>'
context.REQUEST.RESPONSE.setHeader('Content-Type', 'text/html')
return printed
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_reportVirtualMasterMigration2</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
portal = context.getPortalObject()
tag = script.id
### Create the bootstrap Trade Condition
currency = portal.restrictedTraverse('currency_module/EUR')
seller_organisation = portal.restrictedTraverse('organisation_module/rapidspace')
business_process = portal.restrictedTraverse('business_process_module/slapos_ultimate_business_process')
if portal.portal_catalog.getResultValue(
portal_type='Sale Trade Condition',
specialise__uid=business_process.getUid()
) is None:
# Sale Trade Condition for Tax
sale_trade_condition = portal.sale_trade_condition_module.newContent(
portal_type="Sale Trade Condition",
reference="Tax/payment for: %s" % currency.getRelativeUrl(),
trade_condition_type="default",
# XXX hardcoded
specialise_value=business_process,
price_currency_value=currency
)
sale_trade_condition.newContent(
portal_type="Trade Model Line",
reference="VAT",
resource="service_module/slapos_tax",
base_application="base_amount/invoicing/taxable",
trade_phase="slapos/tax",
price=0.2,
quantity=1.0,
membership_criterion_base_category=('price_currency', 'base_contribution'),
membership_criterion_category=('price_currency/%s' % currency.getRelativeUrl(), 'base_contribution/base_amount/invoicing/taxable')
)
sale_trade_condition.validate()
sale_trade_condition.reindexObject(activate_kw={'tag': tag})
# Create Trade Condition to create Project
sale_trade_condition = portal.sale_trade_condition_module.newContent(
portal_type="Sale Trade Condition",
reference="Free Virtual Master (%s)" % seller_organisation.getTitle(),
trade_condition_type="virtual_master",
specialise_value=sale_trade_condition,
source_value=seller_organisation,
price_currency_value=currency,
)
sale_trade_condition.validate()
sale_trade_condition.reindexObject(activate_kw={'tag': tag})
return context.activate(after_tag=tag).Base_triggerFullSiteMigrationToVirtualMasterStep2()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_triggerFullSiteMigrationToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
portal = context.getPortalObject()
tag = script.id
not_migrated_select_dict={'default_follow_up_uid': None}
if run_count == 1:
############################################
# Delete all object to drop
############################################
packet_kw = {
'activate_kw': {'tag': tag},# 'serialization_tag': tag},
'packet_size': 1, # Separate calls to many transactions (calculation can take time)
'activity_count': 1000,
}
portal.portal_catalog.searchAndActivate(
method_id='Base_deleteProcessedDocumentDuringPurge',
portal_type=["Upgrade Decision"],
**packet_kw
)
portal.portal_catalog.searchAndActivate(
method_id='Base_deleteProcessedDocumentDuringPurge',
portal_type=["Regularisation Request"],
**packet_kw
)
############################################
# Migrate existing projects
############################################
portal.project_module.activate(**{'tag': tag, 'priority': 1}).ProjectModule_triggerObjectMigrationToVirtualMaster()
############################################
# Gather compute node informations
############################################
portal.portal_catalog.searchAndActivate(
method_id='ComputeNode_checkSiteMigrationToVirtualMaster',
method_kw={'force_migration': run_count==5},
activate_kw={'tag': tag, 'priority': 1},
portal_type="Compute Node",
select_dict=not_migrated_select_dict,
left_join_list=not_migrated_select_dict.keys(),
**not_migrated_select_dict
)
############################################
# Gather instance tree informations
############################################
portal.portal_catalog.searchAndActivate(
method_id='InstanceTree_checkSiteMigrationToVirtualMaster',
activate_kw={'tag': tag, 'priority': 1},
portal_type="Instance Tree",
select_dict=not_migrated_select_dict,
left_join_list=not_migrated_select_dict.keys(),
**not_migrated_select_dict
)
############################################
# Gather computer network informations
############################################
portal.portal_catalog.searchAndActivate(
method_id='ComputerNetwork_checkSiteMigrationToVirtualMaster',
activate_kw={'tag': tag, 'priority': 1},
portal_type="Computer Network",
select_dict=not_migrated_select_dict,
left_join_list=not_migrated_select_dict.keys(),
**not_migrated_select_dict
)
if run_count < 10:
# Run the migration script multiple times
# Because some object are migrated only after some others are migrated
context.activate(after_tag=tag).Base_triggerFullSiteMigrationToVirtualMasterStep2(run_count=run_count+1)
else:
context.activate(after_tag=tag).Base_triggerFullSiteMigrationToVirtualMasterStep3(run_count=run_count)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>run_count=1</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_triggerFullSiteMigrationToVirtualMasterStep2</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
portal = context.getPortalObject()
tag = script.id
migrated_select_dict={'follow_up__uid': '%'}
############################################
# Delete all object to drop
############################################
packet_kw = {
'activate_kw': {'tag': tag},# 'serialization_tag': tag},
'packet_size': 1, # Separate calls to many transactions (calculation can take time)
'activity_count': 1000,
}
portal.portal_catalog.searchAndActivate(
method_id='Base_deleteProcessedDocumentDuringPurge',
portal_type=["Internal Packing List"],
**packet_kw
)
# Delete existing old product only
if portal.portal_catalog.getResultValue(portal_type="Software Release") is not None:
portal.portal_catalog.searchAndActivate(
method_id='Base_deleteProcessedDocumentDuringPurge',
portal_type=["Software Product", "Software Release"],
**packet_kw
)
############################################
# Gather compute node informations
############################################
portal.portal_catalog.searchAndActivate(
method_id='ComputeNode_fixupSiteMigrationToVirtualMaster',
activate_kw={'tag': tag, 'priority': 1},
portal_type="Compute Node",
**migrated_select_dict
)
############################################
# Gather instance tree informations
############################################
portal.portal_catalog.searchAndActivate(
method_id='InstanceTree_fixupSiteMigrationToVirtualMaster',
method_kw={'tag': tag},
activate_kw={'tag': tag, 'priority': 1},
portal_type="Instance Tree",
**migrated_select_dict
)
if (run_count == 10):
context.activate(after_tag=tag).Base_triggerFullSiteMigrationToVirtualMasterStep2(run_count=run_count+1)
else:
context.activate(after_tag=tag).Base_triggerFullSiteMigrationToVirtualMasterStep4()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>run_count=-1</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_triggerFullSiteMigrationToVirtualMasterStep3</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# create the software products
################################################
portal = context.getPortalObject()
tag = script.id
############################################
# Create products per project
############################################
portal.portal_catalog.searchAndActivate(
method_id='Project_checkSoftwareProductToVirtualMaster',
method_kw={'activate_kw': {'tag': tag}},
activate_kw={'tag': tag, 'priority': 1},
portal_type="Project",
)
############################################
# Create instance node per project
############################################
portal.portal_catalog.searchAndActivate(
method_id='Project_checkInstanceNodeToVirtualMaster',
method_kw={'activate_kw': {'tag': tag}},
activate_kw={'tag': tag, 'priority': 1},
portal_type="Project",
)
context.activate(after_tag=tag).Base_triggerFullSiteMigrationToVirtualMasterStep5()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_triggerFullSiteMigrationToVirtualMasterStep4</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# create the software products
################################################
portal = context.getPortalObject()
tag = script.id
############################################
# Create allocation supply
############################################
packet_kw = {
'method_kw': {'activate_kw': {'tag': tag}},
'activate_kw': {'tag': tag, 'priority': 1},
'packet_size': 1, # Separate calls to many transactions (calculation can take time)
'activity_count': 1000,
}
portal.portal_catalog.searchAndActivate(
method_id='ComputeNode_checkAllocationSupplyToVirtualMaster',
portal_type="Compute Node",
allocation_scope__uid=portal.portal_categories.allocation_scope.open.getUid(),
**packet_kw
)
portal.portal_catalog.searchAndActivate(
method_id='RemoteNode_checkAllocationSupplyToVirtualMaster',
portal_type="Remote Node",
allocation_scope__uid=portal.portal_categories.allocation_scope.open.getUid(),
**packet_kw
)
portal.portal_catalog.searchAndActivate(
method_id='InstanceNode_checkAllocationSupplyToVirtualMaster',
portal_type="Instance Node",
**packet_kw
)
context.activate(after_tag=tag).getId()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_triggerFullSiteMigrationToVirtualMasterStep5</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
compute_node = context
# If there is already a related allocation supply, do nothing
if portal.portal_catalog.getResultValue(portal_type="Allocation Supply",
aggregate__uid=compute_node.getUid()) is not None:
return
slave_on_same_instance_tree_allocable_product_dict = {}
not_slave_on_same_instance_tree_allocable_product_dict = {}
# will contains:
# {node_relative_url: {product_list: xxx, slave_on_same_instance_tree_allocable: boolean}}
for sql_partition_result in compute_node.contentValues(
portal_type=["Compute Partition"]
):
partition = sql_partition_result.getObject()
if partition.getSlapState() == 'busy':
for sql_instance_result in portal.portal_catalog(
portal_type="Software Instance",
aggregate__uid=partition.getUid(),
slap_state=['start_requested', 'stop_requested']
):
software_instance = sql_instance_result.getObject()
software_instance_node = portal.portal_catalog.getResultValue(portal_type="Instance Node", specialise__uid=software_instance.getUid())
software_product, release_variation, type_variation = software_instance.InstanceTree_getSoftwareProduct()
if software_product is None:
raise NotImplementedError(software_instance.getRelativeUrl())
slave_on_same_instance_tree_allocable = (software_instance_node is None) and \
(portal.portal_catalog.getResultValue(
portal_type="Slave Instance",
aggregate__uid=partition.getUid()
) is not None)
if slave_on_same_instance_tree_allocable:
product_dict = slave_on_same_instance_tree_allocable_product_dict
else:
product_dict = not_slave_on_same_instance_tree_allocable_product_dict
if software_product.getRelativeUrl() not in product_dict:
product_dict[software_product.getRelativeUrl()] = {}
if type_variation.getRelativeUrl() not in product_dict[software_product.getRelativeUrl()]:
product_dict[software_product.getRelativeUrl()][type_variation.getRelativeUrl()] = set()
product_dict[software_product.getRelativeUrl()][type_variation.getRelativeUrl()].add(release_variation.getRelativeUrl())
for slave_on_same_instance_tree_allocable, product_dict in [
(True, slave_on_same_instance_tree_allocable_product_dict),
(False, not_slave_on_same_instance_tree_allocable_product_dict)
]:
if product_dict:
# Time to create the allocation supply
#print product_dict
allocation_supply = portal.allocation_supply_module.newContent(
title="%s %s" % (compute_node.getReference(), DateTime().rfc822()),
portal_type="Allocation Supply",
slave_on_same_instance_tree_allocable=slave_on_same_instance_tree_allocable,
destination_project_value=compute_node.getFollowUpValue(),
start_date_range_min=DateTime(),
aggregate_value=compute_node,
activate_kw=activate_kw
)
for software_product_relative_url in product_dict:
software_product = portal.restrictedTraverse(software_product_relative_url)
allocation_supply_line = allocation_supply.newContent(
portal_type="Allocation Supply Line",
title=software_product.getTitle(),
resource_value=software_product,
activate_kw=activate_kw
)
allocation_supply_line.edit(
p_variation_base_category_list=allocation_supply_line.getVariationRangeBaseCategoryList(),
activate_kw=activate_kw
)
base_id = 'path'
allocation_supply_line.setCellRange(
base_id=base_id,
*allocation_supply_line.SupplyLine_asCellRange(base_id=base_id)
)
for type_variation_relative_url in product_dict[software_product_relative_url]:
for release_variation_relative_url in product_dict[software_product_relative_url][type_variation_relative_url]:
# create cells
resource_vcl = [
'software_release/%s' % release_variation_relative_url,
'software_type/%s' % type_variation_relative_url
]
resource_vcl.sort()
cell_key = resource_vcl
allocation_supply_cell = allocation_supply_line.newCell(
base_id=base_id,
portal_type='Allocation Supply Cell',
*cell_key
)
allocation_supply_cell.edit(
mapped_value_property_list=['allocable'],
allocable=True,
predicate_category_list=cell_key,
variation_category_list=cell_key,
activate_kw=activate_kw
)
allocation_supply.validate()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>REQUEST=None, activate_kw=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ComputeNode_checkAllocationSupplyToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
not_migrated_compute_node_dict = {}
portal = context.getPortalObject()
compute_node = context.getObject()
compute_node_relative_url = compute_node.getRelativeUrl()
last_affectation_list = compute_node.Item_getAffectationList()
project_relative_url = None
if last_affectation_list and last_affectation_list[0].project_uid:
project_uid = last_affectation_list[0].project_uid
project_relative_url = portal.portal_catalog.getResultValue(uid=project_uid).getRelativeUrl()
not_migrated_compute_node = {
'title': compute_node.getTitle(),
'allocation_scope': compute_node.getAllocationScope(""),
'project_relative_url': project_relative_url,
# Category has been dropped from the Compute Node portal type
'source_administration': ([x[len('source_administration/'):] for x in compute_node.getCategoryList() if x.startswith('source_administration')] or [None])[0],
'instance_list': []
}
source_administration_value = portal.restrictedTraverse(not_migrated_compute_node['source_administration'])
not_migrated_compute_node_dict[compute_node_relative_url] = not_migrated_compute_node
partition_list = compute_node.contentValues(portal_type='Compute Partition')
instance_tree_list = []
for partition in partition_list:
instance_list = portal.portal_catalog(
portal_type=['Slave Instance', 'Software Instance'],
aggregate__uid=partition.getUid()
)
not_migrated_compute_node['instance_list'].extend([x.getRelativeUrl() for x in instance_list])
for instance in instance_list:
instance_tree_list.append(instance.getSpecialiseValue())
# XXX check if the instance tree is only hosted on this machine
instance_tree_list = list(set(instance_tree_list))
computer_network = compute_node.getSubordinationValue(portal_type="Computer Network")
# Already migrate unused compute node
if (len(not_migrated_compute_node['instance_list']) == 0) and \
(not_migrated_compute_node['project_relative_url'] is None) and \
((not not_migrated_compute_node['allocation_scope'].startswith('open')) or (not_migrated_compute_node['allocation_scope'] == 'open/personal')):
not_migrated_compute_node_dict.pop(compute_node_relative_url)
source_administration_value.Person_checkSiteMigrationCreatePersonalVirtualMaster([compute_node_relative_url])
# Node linked to a project
elif not_migrated_compute_node['project_relative_url'] is not None:
compute_node.activate().Base_activateObjectMigrationToVirtualMaster(not_migrated_compute_node['project_relative_url'])
not_migrated_compute_node_dict.pop(compute_node_relative_url)
elif (computer_network is not None) and (computer_network.getFollowUp(None) is not None):
# Network is already linked to a project
compute_node.activate().Base_activateObjectMigrationToVirtualMaster(computer_network.getFollowUp())
not_migrated_compute_node_dict.pop(compute_node_relative_url)
elif force_migration and (not_migrated_compute_node['source_administration'] is not None):
# Create a single project for every single remaining compute node
project = source_administration_value.Person_addVirtualMaster(
title='Migrated shared for %s' % compute_node.getReference(),
is_compute_node_payable=False,
is_instance_tree_payable=False,
# Hardcoded
price_currency='currency_module/EUR',
batch=1
)
compute_node.activate().Base_activateObjectMigrationToVirtualMaster(project.getRelativeUrl())
not_migrated_compute_node_dict.pop(compute_node_relative_url)
else:
# If the related instance are all grouped on this machine, and from the same user
from_same_user_only = True
instance_project_list = []
for instance_tree in instance_tree_list:
instance_project_list.append(instance_tree.getFollowUp(None))
if instance_tree.getDestinationSection() != not_migrated_compute_node['source_administration']:
from_same_user_only = False
else:
for software_instance in instance_tree.getFollowUpRelatedValueList():
partition = software_instance.getAggregate(None)
if (partition is not None) and (partition.startswith(compute_node_relative_url)):
from_same_user_only = False
instance_project_list = list(set(instance_project_list))
if from_same_user_only:
not_migrated_compute_node_dict.pop(compute_node_relative_url)
source_administration_value.Person_checkSiteMigrationCreatePersonalVirtualMaster([compute_node_relative_url] + [x.getRelativeUrl() for x in instance_tree_list])
elif (len(instance_project_list) == 1) and (instance_project_list[0] is not None):
# Else, check if all related instances tree are on the same virtual master
not_migrated_compute_node_dict.pop(compute_node_relative_url)
compute_node.activate().Base_activateObjectMigrationToVirtualMaster(instance_project_list[0])
# Log
if not_migrated_compute_node_dict:
context.log(not_migrated_compute_node_dict.keys())
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>force_migration=False, REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ComputeNode_checkSiteMigrationToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
compute_node = context.getObject()
computer_network = compute_node.getSubordinationValue()
if (computer_network is not None) and (compute_node.getFollowUp() != computer_network.getFollowUp()):
compute_node.edit(subordination=None)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>force_migration=False, REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ComputeNode_fixupSiteMigrationToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
compute_node = context
project = portal.restrictedTraverse(project_relative_url)
edit_kw = {}
# Check if it has been migrated first
if compute_node.getFollowUpValue() is None:
edit_kw['follow_up_value'] = project
if compute_node.getAllocationScope('').startswith('open/'):
edit_kw['allocation_scope'] = 'open'
# Migrate
if edit_kw:
compute_node.edit(**edit_kw)
# Drop outdated categories
category_list = compute_node.getCategoryList()
new_category_list = [x for x in category_list if not x.startswith('source_administration')]
if len(category_list) != len(new_category_list):
compute_node.setCategoryList(new_category_list)
# Trigger migrations of related objects
portal.portal_catalog.searchAndActivate(
method_id='Base_activateObjectMigrationToVirtualMaster',
method_args=[project_relative_url],
portal_type='Software Installation',
aggregate__uid=compute_node.getUid()
)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>project_relative_url, REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ComputeNode_triggerObjectMigrationToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
computer_network = context.getObject()
computer_network_relative_url = computer_network.getRelativeUrl()
last_affectation_list = computer_network.Item_getAffectationList()
project_relative_url = None
if last_affectation_list and last_affectation_list[0].project_uid:
project_uid = last_affectation_list[0].project_uid
project_relative_url = portal.portal_catalog.getResultValue(uid=project_uid).getRelativeUrl()
not_migrated_computer_network = {
'title': computer_network.getTitle(),
'project_relative_url': project_relative_url,
# Category has been dropped from the Computer Network portal type
'source_administration': ([x[len('source_administration/'):] for x in computer_network.getCategoryList() if x.startswith('source_administration')] or [None])[0],
}
# If network has no compute node, move it to user personal project
compute_node_list = [x.getObject() for x in portal.portal_catalog(
portal_type="Compute Node",
subordination__uid=computer_network.getUid()
)]
project_list = [x.getFollowUp(None) for x in compute_node_list]
project_list = list(set(project_list))
# Node linked to a project
if not_migrated_computer_network['project_relative_url'] is not None:
computer_network.activate().Base_activateObjectMigrationToVirtualMaster(not_migrated_computer_network['project_relative_url'])
elif (len(compute_node_list) == 0) and (not_migrated_computer_network['source_administration'] is not None):
# No compute node. Move it to user personal project
source_administration_value = portal.restrictedTraverse(not_migrated_computer_network['source_administration'])
source_administration_value.Person_checkSiteMigrationCreatePersonalVirtualMaster([computer_network_relative_url])
elif (len(project_list) == 1) and (project_list[0] is not None):
# All nodes are linked to the same project
computer_network.activate().Base_activateObjectMigrationToVirtualMaster(project_list[0])
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ComputerNetwork_checkSiteMigrationToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
computer_network = context
project = portal.restrictedTraverse(project_relative_url)
edit_kw = {}
# Check if it has been migrated first
if computer_network.getFollowUpValue() is None:
edit_kw['follow_up_value'] = project
# Migrate
if edit_kw:
computer_network.edit(**edit_kw)
# Drop outdated categories
category_list = computer_network.getCategoryList()
new_category_list = [x for x in category_list if not x.startswith('source_administration')]
if len(category_list) != len(new_category_list):
computer_network.setCategoryList(new_category_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>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>project_relative_url, REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ComputerNetwork_triggerObjectMigrationToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
instance_node = context
# If there is already a related allocation supply, do nothing
if portal.portal_catalog.getResultValue(portal_type="Allocation Supply",
aggregate__uid=instance_node.getUid()) is not None:
return
product_dict = {}
software_instance = instance_node.getSpecialiseValue()
partition = software_instance.getAggregateValue()
if (partition is None) or (software_instance.getSlapState() != 'start_requested'):
return
for sql_instance_result in portal.portal_catalog(
portal_type=["Slave Instance"],
aggregate__uid=partition.getUid(),
):
slave_instance = sql_instance_result.getObject()
if slave_instance.getSlapState() in ["start_requested", "stop_requested"]:
software_product, release_variation, type_variation = slave_instance.InstanceTree_getSoftwareProduct()
if software_product is None:
raise NotImplementedError(slave_instance.getRelativeUrl())
if software_product.getRelativeUrl() not in product_dict:
product_dict[software_product.getRelativeUrl()] = {}
if type_variation.getRelativeUrl() not in product_dict[software_product.getRelativeUrl()]:
product_dict[software_product.getRelativeUrl()][type_variation.getRelativeUrl()] = set()
product_dict[software_product.getRelativeUrl()][type_variation.getRelativeUrl()].add(release_variation.getRelativeUrl())
for slave_on_same_instance_tree_allocable, product_dict in [
(False, product_dict)
]:
if product_dict:
# Time to create the allocation supply
#print product_dict
allocation_supply = portal.allocation_supply_module.newContent(
title="%s %s" % (instance_node.getReference(), DateTime().rfc822()),
portal_type="Allocation Supply",
slave_on_same_instance_tree_allocable=slave_on_same_instance_tree_allocable,
destination_project_value=instance_node.getFollowUpValue(),
start_date_range_min=DateTime(),
aggregate_value=instance_node,
activate_kw=activate_kw
)
for software_product_relative_url in product_dict:
software_product = portal.restrictedTraverse(software_product_relative_url)
allocation_supply_line = allocation_supply.newContent(
portal_type="Allocation Supply Line",
title=software_product.getTitle(),
resource_value=software_product,
activate_kw=activate_kw
)
allocation_supply_line.edit(
p_variation_base_category_list=allocation_supply_line.getVariationRangeBaseCategoryList(),
activate_kw=activate_kw
)
base_id = 'path'
allocation_supply_line.setCellRange(
base_id=base_id,
*allocation_supply_line.SupplyLine_asCellRange(base_id=base_id)
)
for type_variation_relative_url in product_dict[software_product_relative_url]:
for release_variation_relative_url in product_dict[software_product_relative_url][type_variation_relative_url]:
# create cells
resource_vcl = [
'software_release/%s' % release_variation_relative_url,
'software_type/%s' % type_variation_relative_url
]
resource_vcl.sort()
cell_key = resource_vcl
allocation_supply_cell = allocation_supply_line.newCell(
base_id=base_id,
portal_type='Allocation Supply Cell',
*cell_key
)
allocation_supply_cell.edit(
mapped_value_property_list=['allocable'],
allocable=True,
predicate_category_list=cell_key,
variation_category_list=cell_key,
activate_kw=activate_kw
)
allocation_supply.validate()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>REQUEST=None, activate_kw=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>InstanceNode_checkAllocationSupplyToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
not_migrated_instance_tree_dict = {}
portal = context.getPortalObject()
instance_tree = context.getObject()
instance_tree_relative_url = instance_tree.getRelativeUrl()
software_instance = ([x for x in instance_tree.getSuccessorValueList() if x.getTitle()==instance_tree.getTitle()] + [None])[0]
sla_xml_dict = {}
if software_instance is None:
try:
sla_xml_dict = software_instance.getSlaXmlAsDict()
except:
# XMLSyntaxError
pass
last_affectation_list = instance_tree.Item_getAffectationList()
project_relative_url = None
if last_affectation_list and last_affectation_list[0].project_uid:
project_uid = last_affectation_list[0].project_uid
project_relative_url = portal.portal_catalog.getResultValue(uid=project_uid).getRelativeUrl()
not_migrated_instance_tree_dict[instance_tree_relative_url] = {
'title': instance_tree.getTitle(),
'slap_state': instance_tree.getSlapState(),
'destination_section': instance_tree.getDestinationSection(None),
'project_relative_url': project_relative_url,
'allocated_instance_list': []
}
for sql_instance in portal.portal_catalog(specialise__uid=instance_tree.getUid()):
if sql_instance.getAggregate(None) is not None:
not_migrated_instance_tree_dict[instance_tree_relative_url]['allocated_instance_list'].append(sql_instance.getRelativeUrl())
# Node linked to a project
if not_migrated_instance_tree_dict[instance_tree_relative_url]['project_relative_url'] is not None:
instance_tree.activate().Base_activateObjectMigrationToVirtualMaster(not_migrated_instance_tree_dict[instance_tree_relative_url]['project_relative_url'])
not_migrated_instance_tree_dict.pop(instance_tree_relative_url)
# Node requested to be allocated on a specific project
elif (software_instance is not None) and (sla_xml_dict.get('project_guid', None) is not None):
project_reference = sla_xml_dict.get('project_guid', None)
project = portal.portal_catalog.getResultValue(portal_type='Project', reference=project_reference)
if project is not None:
instance_tree.activate().Base_activateObjectMigrationToVirtualMaster(project.getRelativeUrl())
not_migrated_instance_tree_dict.pop(instance_tree_relative_url)
# Node requested to be allocated on a specific node
elif (software_instance is not None) and (sla_xml_dict.get('computer_guid', None) is not None):
project_instance_reference = sla_xml_dict.get('computer_guid', None)
project_instance = portal.portal_catalog.getResultValue(portal_type='Compute Node', reference=project_instance_reference)
if project_instance is not None:
project = project_instance.getFollowUpValue(None)
if project is not None:
instance_tree.activate().Base_activateObjectMigrationToVirtualMaster(project.getRelativeUrl())
not_migrated_instance_tree_dict.pop(instance_tree_relative_url)
# Slave Node requested to be allocated on a specific project instance
elif (software_instance is not None) and (sla_xml_dict.get('instance_guid', None) is not None):
project_instance_reference = sla_xml_dict.get('instance_guid', None)
project_instance = portal.portal_catalog.getResultValue(portal_type='Software Instance', reference=project_instance_reference)
if project_instance is not None:
project = project_instance.getFollowUpValue(None)
if project is not None:
instance_tree.activate().Base_activateObjectMigrationToVirtualMaster(project.getRelativeUrl())
not_migrated_instance_tree_dict.pop(instance_tree_relative_url)
# Finally, use the same project than the allocation
elif (software_instance is not None) and (software_instance.getAggregateValue(None) is not None):
project = software_instance.getAggregateValue().getParentValue().getFollowUpValue(None)
if project is not None:
instance_tree.activate().Base_activateObjectMigrationToVirtualMaster(project.getRelativeUrl())
not_migrated_instance_tree_dict.pop(instance_tree_relative_url)
# If no instance is allocated, it will probably never be. Move to personal
elif ((len(not_migrated_instance_tree_dict[instance_tree_relative_url]['allocated_instance_list']) == 0) and
(not_migrated_instance_tree_dict[instance_tree_relative_url]['destination_section'] is not None)):
instance_tree.getDestinationSectionValue().Person_checkSiteMigrationCreatePersonalVirtualMaster([instance_tree_relative_url])
not_migrated_instance_tree_dict.pop(instance_tree_relative_url)
# Outdated instance tree will move to the personal project
# as, there is no way to know where it has been allocated previously
elif (not_migrated_instance_tree_dict[instance_tree_relative_url]['slap_state'] == 'destroy_requested') and \
(not_migrated_instance_tree_dict[instance_tree_relative_url]['project_relative_url'] is None) and \
(not_migrated_instance_tree_dict[instance_tree_relative_url]['destination_section'] is not None):
instance_tree.getDestinationSectionValue().Person_checkSiteMigrationCreatePersonalVirtualMaster([instance_tree_relative_url])
not_migrated_instance_tree_dict.pop(instance_tree_relative_url)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>InstanceTree_checkSiteMigrationToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
instance_tree = context.getObject()
instance_tree_virtual_master = instance_tree.getFollowUpValue()
instance_tree_virtual_master_relative_url = instance_tree_virtual_master.getRelativeUrl()
# Check recursively the instance tree
# and detect orphaned nodes
is_orphaned_instance_dict = {}
for successor in instance_tree.getSuccessorList():
is_orphaned_instance_dict[successor] = False
for sql_result in portal.portal_catalog(specialise__uid=instance_tree.getUid()):
instance = sql_result.getObject()
if instance.getRelativeUrl() not in is_orphaned_instance_dict:
is_orphaned_instance_dict[instance.getRelativeUrl()] = True
for successor in instance.getSuccessorList():
is_orphaned_instance_dict[successor] = False
# Then, browser the roots, and stop as soon as one with a different virtual master is found
# all its successors will be moved to if needed
instance_to_check_list = [portal.restrictedTraverse(x) for x in is_orphaned_instance_dict if is_orphaned_instance_dict[x]]
instance_to_check_list.extend(instance_tree.getSuccessorValueList())
remote_virtual_master_dict = {}
while instance_to_check_list:
instance = instance_to_check_list.pop()
is_consistent = True
partition = instance.getAggregateValue()
if partition is not None:
instance_virtual_master_relative_url = partition.getParentValue().getFollowUp(None)
if (instance_virtual_master_relative_url is not None) and (instance_virtual_master_relative_url != instance_tree_virtual_master_relative_url):
if instance_virtual_master_relative_url not in remote_virtual_master_dict:
remote_virtual_master_dict[instance_virtual_master_relative_url] = []
remote_virtual_master_dict[instance_virtual_master_relative_url].append(instance.getRelativeUrl())
is_consistent = False
if is_consistent:
# Check sub instances only if parent is ok
instance_to_check_list.extend(instance.getSuccessorValueList())
# Trigger migration
for instance_virtual_master_relative_url in remote_virtual_master_dict:
instance_tree_virtual_master.Project_checkSiteMigrationCreateRemoteNode(
instance_virtual_master_relative_url,
remote_virtual_master_dict[instance_virtual_master_relative_url],
activate_kw={'tag': tag, 'serialization_tag': tag, 'limit': 1}
)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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=None, REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>InstanceTree_fixupSiteMigrationToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
instance_tree = context
project = portal.restrictedTraverse(project_relative_url)
edit_kw = {}
# Check if it has been migrated first
if instance_tree.getFollowUpValue() is None:
edit_kw['follow_up_value'] = project
# Migrate
if edit_kw:
instance_tree.edit(**edit_kw)
# Trigger migrations of related objects
portal.portal_catalog.searchAndActivate(
method_id='Base_activateObjectMigrationToVirtualMaster',
method_args=[project_relative_url],
portal_type=['Software Instance', 'Slave Instance'],
specialise__uid=instance_tree.getUid()
)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>project_relative_url, REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>InstanceTree_triggerObjectMigrationToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
person = context
is_first_call = (tag is None)
tag = "%s_%s" % (person.getUid(), script.id)
activate_kw = {
'tag': tag
}
wait_activate_kw = {
'activity': 'SQLQueue',
'serialization_tag': tag,
'after_tag': tag
}
# Search the existing virtual master
virtual_master_title = 'Migrated personal for %s' % person.getTitle()
project = portal.portal_catalog.getResultValue(
portal_type='Project',
destination__uid=person.getUid(),
title={'query': virtual_master_title, 'key': 'ExactMatch'}
)
if project is None:
# Delay the script to prevent conflict with serialize
# in the caller script
# Prevent concurrent activities
if is_first_call or (0 < portal.portal_activities.countMessageWithTag(tag)):
return person.activate(**wait_activate_kw).Person_checkSiteMigrationCreatePersonalVirtualMaster(relative_url_to_migrate_list, tag=tag, *args, **kw)
person.serialize()
# No concurrent activity.
# Create it
project = person.Person_addVirtualMaster(
title=virtual_master_title,
is_compute_node_payable=False,
is_instance_tree_payable=False,
# Hardcoded
price_currency='currency_module/EUR',
batch=1,
activate_kw=activate_kw
)
# XXX Then, migrate other documents linked to the virtual master
for relative_url_to_migrate in relative_url_to_migrate_list:
object_to_migrate = portal.restrictedTraverse(relative_url_to_migrate)
object_to_migrate.activate().Base_activateObjectMigrationToVirtualMaster(project.getRelativeUrl())
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>relative_url_to_migrate_list, REQUEST=None, tag=None, *args, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Person_checkSiteMigrationCreatePersonalVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
activate_kw = None
##########################################################################
## Find the list of all project where instances must be paid
##########################################################################
payable_project_guid_dict = {}
for sql_result in portal.portal_catalog(
portal_type="Subscription Request",
):
subscription_request = sql_result.getObject()
if subscription_request.getSpecialise('').startswith('subscription_condition'):
instance_tree = subscription_request.getAggregateValue(portal_type="Instance Tree")
if (instance_tree is not None):
context.log('COUSCOUS %s' % subscription_request.getRelativeUrl())
# Build the list of prices per project/software release
project_guid = instance_tree.getSuccessorValue().getSlaXmlAsDict().get('project_guid', None)
if project_guid is not None:
payable_project_guid_dict[project_guid] = subscription_request.getPriceCurrency()
# Delete existing subscription request, which must be recreated later
subscription_request.getParentValue().manage_delObjects(ids=[subscription_request.getId()])
##########################################################################
## Migrate all existing projects
##########################################################################
# Copied from Person_addVirtualMaster
project_resource = portal.restrictedTraverse("service_module/slapos_virtual_master_subscription")
for sql_result in portal.portal_catalog(
portal_type="Project",
):
project = sql_result.getObject()
if project.getDestinationValue(None) is None:
# Project is not migrated
customer = project.getDestinationDecisionValue(None)
if (customer is None) or (project.getValidationState() != 'validated'):
# No idea how to migrate this project
continue
project.edit(
destination_value=customer,
destination_decision_value=None
)
is_compute_node_payable = False
is_instance_tree_payable = False
# XXX hardcoded
price_currency = 'currency_module/EUR'
if project.getReference() in payable_project_guid_dict:
is_instance_tree_payable = True
price_currency = payable_project_guid_dict[project.getReference()]
currency_value = portal.restrictedTraverse(price_currency)
# create the subscription request, which will lead to the Open Order
subscription_request = project_resource.Resource_createSubscriptionRequest(customer, [], project, currency_value=currency_value)
subscription_request.reindexObject(activate_kw=activate_kw)
# XXX How to specify the trade condition containing the currency and trade model lines?
specialise_value = subscription_request.getSpecialiseValue(portal_type="Sale Trade Condition")
if ((specialise_value is not None) and
(len(specialise_value.contentValues(portal_type="Trade Model Line")) == 0)):
specialise_value = specialise_value.getSpecialiseValue(portal_type="Sale Trade Condition")
if ((specialise_value is None) or
(len(specialise_value.contentValues(portal_type="Trade Model Line")) == 0)):
raise ValueError('Could not find a Trade Condition with Trade Model Line')
# and create default assignments for the user
# who can manage compute nodes and create instances
customer.newContent(
portal_type='Assignment',
destination_project_value=project,
function='production/manager',
activate_kw=activate_kw
).open()
customer.newContent(
portal_type='Assignment',
destination_project_value=project,
function='customer',
activate_kw=activate_kw
).open()
for is_payable, portal_type, trade_condition_type in [
(is_compute_node_payable, 'Compute Node', "compute_node"),
(is_instance_tree_payable, 'Instance Tree', "instance_tree"),
]:
if is_payable:
source_section_value = subscription_request.getSourceSectionValue(
default=subscription_request.getSourceValue(default=None, portal_type='Organisation'),
portal_type='Organisation'
)
if source_section_value is None:
raise AssertionError('No source section found to generate the invoices')
title = 'Payable %s for: %s' % (portal_type, project.getTitle())
else:
source_section_value = None
title = 'Free %s for: %s' % (portal_type, project.getTitle())
sale_trade_condition = portal.sale_trade_condition_module.newContent(
portal_type="Sale Trade Condition",
reference=title,
trade_condition_type=trade_condition_type,
specialise_value=specialise_value,
source_project_value=project,
source_value=subscription_request.getSourceValue(),
source_section_value=source_section_value,
#source_payment_value=seller_bank_account,
price_currency_value=currency_value,
activate_kw=activate_kw
)
sale_trade_condition.validate()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ProjectModule_triggerObjectMigrationToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
project = context
group_by_list = ["aggregate__uid"]
sql_result_list = portal.portal_catalog(
select_list=group_by_list,
portal_type=["Slave Instance"],
follow_up__uid=project.getUid(),
group_by=group_by_list
)
for sql_result in sql_result_list:
slave_instance = sql_result.getObject()
partition = slave_instance.getAggregateValue()
if (partition is not None) and (partition.getParentValue().getPortalType() == 'Compute Node'):
instance_list = portal.portal_catalog(
portal_type="Software Instance",
aggregate__uid=partition.getUid(),
limit=2
)
if (len(instance_list) == 1) and (instance_list[0].getSpecialise() != slave_instance.getSpecialise()):
software_instance = instance_list[0]
instance_tree = software_instance.getSpecialiseValue()
if portal.portal_catalog.getResultValue(
portal_type="Instance Node",
specialise__uid=software_instance.getUid()
) is None:
instance_node = portal.compute_node_module.newContent(
portal_type='Instance Node',
title=instance_tree.getTitle(),
specialise_value=software_instance,
follow_up_value=software_instance.getFollowUpValue(),
activate_kw=activate_kw
)
instance_node.validate()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>REQUEST=None, activate_kw=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Project_checkInstanceNodeToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
project = context
is_first_call = (tag is None)
tag = "%s_%s_%s" % (project.getUid(), script.id, remote_project_relative_url)
activate_kw = {
'tag': tag
}
wait_activate_kw = {
'activity': 'SQLQueue',
'serialization_tag': tag,
'after_tag': tag
}
remote_project = portal.restrictedTraverse(remote_project_relative_url)
# Search the existing virtual master
remote_node_title = 'Migrated remote to %s' % remote_project.getReference()
remote_node = portal.portal_catalog.getResultValue(
portal_type='Remote Node',
destination_project__uid=remote_project.getUid(),
follow_up__uid=project.getUid(),
title={'query': remote_node_title, 'key': 'ExactMatch'}
)
if remote_node is None:
# Delay the script to prevent conflict with serialize
# in the caller script
# Prevent concurrent activities
if is_first_call or (0 < portal.portal_activities.countMessageWithTag(tag)):
return project.activate(**wait_activate_kw).Project_checkSiteMigrationCreateRemoteNode(remote_project_relative_url, relative_url_to_migrate_list, tag=tag, *args, **kw)
project.serialize()
# No concurrent activity.
# Create it
# XXX copied from Project_addSlapOSRemoteNode
remote_node = portal.compute_node_module.newContent(
portal_type='Remote Node',
title=remote_node_title,
# Use the project owner
destination_section_value=remote_project.getDestinationValue(),
destination_project_value=remote_project,
follow_up_value=project,
allocation_scope='open',
activate_kw=activate_kw
)
remote_node.validate()
remote_node.reindexObject(activate_kw=activate_kw)
# XXX Then, migrate other documents linked to the virtual master
portal.portal_catalog.searchAndActivate(
method_id='Base_activateObjectMigrationToRemoteVirtualMaster',
method_args=[remote_node.getRelativeUrl()],
activate_kw=activate_kw,
# Go slowly, because it generate DB conflicts
packet_size=1,
activity_count=1000,
relative_url=relative_url_to_migrate_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>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>remote_project_relative_url, relative_url_to_migrate_list, REQUEST=None, tag=None, activate_kw=None, *args, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Project_checkSiteMigrationCreateRemoteNode</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
project = context
def calculateSoftwareProductTitle(software_release_url):
if not software_release_url.startswith('http'):
return software_release_url
try:
result = software_release_url.split('/')[-2]
except IndexError:
result = software_release_url
if not software_release_url.endswith('software.cfg'):
result += ' %s' % software_release_url.split('/')[-1]
return result
soft_dict = {}
###########################################################
# First, calculate the list of product by checking the instances
###########################################################
group_by_list = ["url_string", "follow_up__uid", "source_reference"]
sql_result_list = portal.portal_catalog(
portal_type=["Software Instance", "Slave Instance"],
slap_state=["start_requested", "stop_requested"],
follow_up__uid=project.getUid()
)
for sql_result in sql_result_list:
software_release_url = sql_result.getUrlString()
software_product_title = calculateSoftwareProductTitle(software_release_url)
if software_product_title not in soft_dict:
soft_dict[software_product_title] = {
'release_list': [],
'type_list': []
}
soft_dict[software_product_title]['release_list'].append(software_release_url)
soft_dict[software_product_title]['type_list'].append(sql_result.getSourceReference())
###########################################################
# Second, get info from all installed softwares
###########################################################
group_by_list = ["url_string", "follow_up__uid"]
sql_result_list = portal.portal_catalog(
select_list=group_by_list,
portal_type="Software Installation",
slap_state=["start_requested"],
follow_up__uid=project.getUid(),
group_by=group_by_list,
)
for sql_result in sql_result_list:
compute_node = sql_result.getAggregateValue()
if (compute_node is not None) and (compute_node.getAllocationScope() == 'open'):
software_release_url = sql_result['url_string']
software_product_title = calculateSoftwareProductTitle(software_release_url)
if software_product_title not in soft_dict:
soft_dict[software_product_title] = {
'release_list': [],
'type_list': []
}
soft_dict[software_product_title]['release_list'].append(software_release_url)
###########################################################
# Create needed Software Product
###########################################################
for soft, variation_dict in soft_dict.items():
software_product = portal.portal_catalog.getResultValue(
portal_type="Software Product",
title={'query': soft, 'key': 'ExactMatch'},
follow_up__uid=project.getUid()
)
if software_product is None:
software_product = portal.software_product_module.newContent(
portal_type="Software Product",
title=soft,
follow_up_value=project,
activate_kw=activate_kw
)
software_product.validate()
for software_type in list(set(variation_dict['type_list'])):
type_variation = portal.portal_catalog.getResultValue(
portal_type="Software Product Type Variation",
title={'query': software_type, 'key': 'ExactMatch'},
parent_uid=software_product.getUid()
)
if type_variation is None:
software_product.newContent(
portal_type="Software Product Type Variation",
title=software_type,
activate_kw=activate_kw
)
release_list = list(set(variation_dict['release_list']))
release_list.sort()
for software_release in release_list:
software_release_variation = portal.portal_catalog.getResultValue(
portal_type="Software Product Release Variation",
url_string={'query': software_release, 'key': 'ExactMatch'},
parent_uid=software_product.getUid()
)
if software_release_variation is None:
software_product.newContent(
portal_type="Software Product Release Variation",
title=software_release,
url_string=software_release,
activate_kw=activate_kw
)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>REQUEST=None, activate_kw=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Project_checkSoftwareProductToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
remote_node = context
# If there is already a related allocation supply, do nothing
if portal.portal_catalog.getResultValue(portal_type="Allocation Supply",
aggregate__uid=remote_node.getUid()) is not None:
return
product_dict = {}
for sql_partition_result in remote_node.contentValues(
portal_type=["Compute Partition"]
):
partition = sql_partition_result.getObject()
if partition.getSlapState() == 'busy':
for sql_instance_result in portal.portal_catalog(
portal_type=["Slave Instance", "Software Instance"],
aggregate__uid=partition.getUid(),
):
software_instance = sql_instance_result.getObject()
if software_instance.getSlapState() in ["start_requested", "stop_requested"]:
software_product, release_variation, type_variation = software_instance.InstanceTree_getSoftwareProduct()
if software_product is None:
raise NotImplementedError(software_instance.getRelativeUrl())
if software_product.getRelativeUrl() not in product_dict:
product_dict[software_product.getRelativeUrl()] = {}
if type_variation.getRelativeUrl() not in product_dict[software_product.getRelativeUrl()]:
product_dict[software_product.getRelativeUrl()][type_variation.getRelativeUrl()] = set()
product_dict[software_product.getRelativeUrl()][type_variation.getRelativeUrl()].add(release_variation.getRelativeUrl())
for slave_on_same_instance_tree_allocable, product_dict in [
(False, product_dict)
]:
if product_dict:
# Time to create the allocation supply
#print product_dict
allocation_supply = portal.allocation_supply_module.newContent(
title="%s %s" % (remote_node.getReference(), DateTime().rfc822()),
portal_type="Allocation Supply",
slave_on_same_instance_tree_allocable=slave_on_same_instance_tree_allocable,
destination_project_value=remote_node.getFollowUpValue(),
start_date_range_min=DateTime(),
aggregate_value=remote_node,
activate_kw=activate_kw
)
for software_product_relative_url in product_dict:
software_product = portal.restrictedTraverse(software_product_relative_url)
allocation_supply_line = allocation_supply.newContent(
portal_type="Allocation Supply Line",
title=software_product.getTitle(),
resource_value=software_product,
activate_kw=activate_kw
)
allocation_supply_line.edit(
p_variation_base_category_list=allocation_supply_line.getVariationRangeBaseCategoryList(),
activate_kw=activate_kw
)
base_id = 'path'
allocation_supply_line.setCellRange(
base_id=base_id,
*allocation_supply_line.SupplyLine_asCellRange(base_id=base_id)
)
for type_variation_relative_url in product_dict[software_product_relative_url]:
for release_variation_relative_url in product_dict[software_product_relative_url][type_variation_relative_url]:
# create cells
resource_vcl = [
'software_release/%s' % release_variation_relative_url,
'software_type/%s' % type_variation_relative_url
]
resource_vcl.sort()
cell_key = resource_vcl
allocation_supply_cell = allocation_supply_line.newCell(
base_id=base_id,
portal_type='Allocation Supply Cell',
*cell_key
)
allocation_supply_cell.edit(
mapped_value_property_list=['allocable'],
allocable=True,
predicate_category_list=cell_key,
variation_category_list=cell_key,
activate_kw=activate_kw
)
allocation_supply.validate()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>REQUEST=None, activate_kw=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>RemoteNode_checkAllocationSupplyToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
return context.SoftwareInstance_triggerObjectMigrationToRemoteVirtualMaster(remote_node_relative_url, REQUEST=REQUEST)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>remote_node_relative_url, REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SlaveInstance_triggerObjectMigrationToRemoteVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
return context.SoftwareInstance_triggerObjectMigrationToVirtualMaster(project_relative_url, REQUEST=REQUEST)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>project_relative_url, REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SlaveInstance_triggerObjectMigrationToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
software_installation = context
project = portal.restrictedTraverse(project_relative_url)
edit_kw = {}
# Check if it has been migrated first
if software_installation.getFollowUpValue() is None:
edit_kw['follow_up_value'] = project
# Migrate
if edit_kw:
software_installation.edit(**edit_kw)
# Drop outdated categories
category_list = software_installation.getCategoryList()
new_category_list = [x for x in category_list if not x.startswith('destination_section')]
if len(category_list) != len(new_category_list):
software_installation.setCategoryList(new_category_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>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>project_relative_url, REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SoftwareInstallation_triggerObjectMigrationToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
instance = context
instance_virtual_master_relative_url = instance.getFollowUp()
connection_xml = instance.getConnectionXml()
remote_node = portal.restrictedTraverse(remote_node_relative_url)
remote_partition = instance.getAggregateValue()
try:
assert instance_virtual_master_relative_url == remote_node.getFollowUp()
assert instance_virtual_master_relative_url != remote_node.getDestinationProject()
assert remote_partition.getFollowUp() == remote_node.getDestinationProject()
except AssertionError:
if instance_virtual_master_relative_url == remote_node.getDestinationProject():
return
# Something wrong here, maybe the instance was already migrated
raise
tag = "%s_%s" % (script.id, instance.getUid())
activate_kw = {'tag': tag}
#########################################################
# Move current instance to the remote node
#########################################################
if instance.getPortalType() == 'Slave Instance':
# All slave instances goes to this magic partition
new_partition = remote_node.restrictedTraverse('SHARED_REMOTE')
elif instance.getPortalType() == 'Software Instance':
new_partition = remote_node.newContent(
portal_type="Compute Partition",
title="slapmigration",
)
new_partition.markFree()
new_partition.validate()
new_partition.markBusy()
else:
raise NotImplementedError('Not supported instance type: %s' % instance.getPortalType())
portal.portal_workflow.doActionFor(instance, action='edit_action', comment="Migrated to a remote node")
instance.edit(aggregate_value=new_partition, activate_kw=activate_kw)
assert new_partition.getSlapState() == 'busy'
#########################################################
# Create a new instance tree on the remote project
#########################################################
new_partition.ComputePartition_propagateRemoteNode(local_instance_list=[instance.getRelativeUrl()])
remote_instance_tree = context.REQUEST.get('request_instance_tree')
requested_software_instance = context.REQUEST.get('request_instance')
if remote_instance_tree is None:
assert (instance.getSlapState() == 'destroy_requested') or (instance.getValidationState() == 'invalidated')
else:
requested_software_instance.edit(
# keep the previous allocation partition
aggregate_value=remote_partition,
# keep the original connection xml
connection_xml=connection_xml,
activate_kw=activate_kw
)
instance.edit(connection_xml=connection_xml, activate_kw=activate_kw)
assert remote_partition.getSlapState() == 'busy'
# CDN compatibility
# invert the instance references, to ensure cdn keep the same domain name
# as we also want to keep subobject (login), change the instance from one tree into another
original_predecessor = instance.getSuccessorRelatedValue()
if original_predecessor is not None:
successor_list = original_predecessor.getSuccessorList()
successor_list = [x.replace(instance.getRelativeUrl(), requested_software_instance.getRelativeUrl()) for x in successor_list]
instance_title = instance.getTitle()
instance_tree = instance.getSpecialiseValue()
new_remote_title = '_remote_%s_%s' % (instance_tree.getFollowUpReference(), requested_software_instance.getReference())
remote_instance_tree.edit(
successor_value=instance,
title=new_remote_title,
activate_kw=activate_kw
)
instance.edit(
title=remote_instance_tree.getTitle(),
specialise_value=remote_instance_tree,
aggregate_value=remote_partition,
follow_up_value=remote_instance_tree.getFollowUpValue(),
activate_kw=activate_kw
)
if original_predecessor is not None:
original_predecessor.edit(
successor_list=successor_list,
activate_kw=activate_kw
)
requested_software_instance.edit(
title=instance_title,
specialise_value=instance_tree,
aggregate_value=new_partition,
follow_up_value=instance_tree.getFollowUpValue(),
activate_kw=activate_kw
)
# Change the specialise value of all successors of the new instance tree
remote_successor_list = instance.getSuccessorValueList()
while remote_successor_list:
remote_successor = remote_successor_list.pop()
remote_successor_list.extend(remote_successor.getSuccessorValueList())
remote_successor.edit(
specialise_value=remote_instance_tree,
follow_up_value=remote_instance_tree.getFollowUpValue(),
activate_kw=activate_kw
)
# Trigger fixup of the newly instance tree if needed
# to continue cleaning up the remaining instances of the tree
remote_instance_tree.activate(after_tag=tag).InstanceTree_fixupSiteMigrationToVirtualMaster()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>remote_node_relative_url, REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SoftwareInstance_triggerObjectMigrationToRemoteVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
software_instance = context
project = portal.restrictedTraverse(project_relative_url)
edit_kw = {}
# Check if it has been migrated first
if software_instance.getFollowUpValue() is None:
edit_kw['follow_up_value'] = project
# Migrate
if edit_kw:
software_instance.edit(**edit_kw)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</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>project_relative_url, REQUEST=None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SoftwareInstance_triggerObjectMigrationToVirtualMaster</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
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