Commit b97349ec authored by Łukasz Nowak's avatar Łukasz Nowak

Merge branch 'master' into external_buildout

parents b376d945 1b1b35c6
0.3 (unreleased) 0.4 (unreleased)
================ ================
* Do not use buildout internally, but rather call bootstrap command of any * Do not use buildout internally, but rather call bootstrap command of any
provided buildout binary. [Łukasz Nowak] provided buildout binary. [Łukasz Nowak]
0.3 (2011-06-14)
================
* slap: Implement SLA by filter_kw in OpenOrder.request. [Łukasz Nowak]
* slap: Timeout network operations. [Łukasz Nowak]
* slapformat: Make slapsoft and slapuser* system users. [Kazuhiko Shiozaki]
* slapgrid: Add more tolerance with supervisord. [Łukasz Nowak]
0.2 (2011-06-01) 0.2 (2011-06-01)
================ ================
......
...@@ -55,27 +55,6 @@ from AccessControl import getSecurityManager\n ...@@ -55,27 +55,6 @@ from AccessControl import getSecurityManager\n
from Products.ERP5Type.Log import log\n from Products.ERP5Type.Log import log\n
\n \n
portal = context.getPortalObject()\n portal = context.getPortalObject()\n
bt = portal.portal_templates.getInstalledBusinessTemplate("erp5_demo_maxma_sample")\n
isTransitionPossible = portal.portal_workflow.isTransitionPossible\n
\n
for obj in portal.portal_catalog(path=["%%/%s" % i.replace("**", "%") for i in bt.getTemplatePathList()]):\n
obj.activate().updateLocalRolesOnSecurityGroups()\n
\n
for document in portal.portal_catalog(portal_type=bt.getTemplatePortalTypeRoleList()):\n
document.updateLocalRolesOnSecurityGroups()\n
\n
conversion_server_hostname = portal.portal_preferences.getPreferredOoodocServerAddress()\n
conversion_server_port = portal.portal_preferences.getPreferredOoodocServerPortNumber()\n
for preference_id in ["default_configurator_preference", "default_configurator_system_preference"]:\n
preference = getattr(portal.portal_preferences, preference_id)\n
if preference.getPortalType() == "System Preference":\n
preference.setPreferredOoodocServerPortNumber(conversion_server_port)\n
preference.setPreferredOoodocServerAddress(conversion_server_hostname)\n
\n
if isTransitionPossible(preference, "enable"):\n
preference.enable()\n
preference.updateLocalRolesOnSecurityGroups()\n
\n
for gadget in portal.portal_gadgets.objectValues():\n for gadget in portal.portal_gadgets.objectValues():\n
if gadget.getValidationState() == \'invisible\':\n if gadget.getValidationState() == \'invisible\':\n
gadget.visible()\n gadget.visible()\n
......
...@@ -95,10 +95,10 @@ bt5_installation_list = ( \n ...@@ -95,10 +95,10 @@ bt5_installation_list = ( \n
\'vifib_crm\', \n \'vifib_crm\', \n
\'vifib_forge_release\', \n \'vifib_forge_release\', \n
\'vifib_software_pdm\', \n \'vifib_software_pdm\', \n
\'vifib_web\', \n \'vifib_web\',\n
\'vifib_open_trade\', \n \'vifib_open_trade\', \n
\'vifib_l10n_fr\'\n \'vifib_l10n_fr\',\n
\'vifib_datas\'\n \'vifib_datas\',\n
\'vifib_erp5\'\n \'vifib_erp5\'\n
)\n )\n
\n \n
......
...@@ -29,42 +29,61 @@ from Products.ERP5Configurator.tests.ConfiguratorTestMixin import \ ...@@ -29,42 +29,61 @@ from Products.ERP5Configurator.tests.ConfiguratorTestMixin import \
TestLiveConfiguratorWorkflowMixin TestLiveConfiguratorWorkflowMixin
from Products.ERP5Type.tests.Sequence import SequenceList from Products.ERP5Type.tests.Sequence import SequenceList
class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin): class TestVifibConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
""" """
Configurator Mixin Class Configurator Mixin Class
""" """
# The list of standard business templates that the configurator should force # The list of standard business templates that the configurator should force
# to install # to install
user_reference = "demo" user_reference = "demo"
standard_bt5_list = ('erp5_simulation', standard_bt5_list = (
'erp5_dhtml_style', 'erp5_simulation',
'erp5_jquery', 'erp5_administration',
'erp5_jquery_ui', 'erp5_pdm',
'erp5_xhtml_jquery_style', 'erp5_trade',
'erp5_ingestion_mysql_innodb_catalog', 'erp5_simulation_test',
'erp5_ingestion', 'erp5_item',
'erp5_web', 'erp5_open_trade',
'erp5_dms', 'erp5_forge',
'erp5_crm', 'erp5_ingestion_mysql_innodb_catalog',
'erp5_pdm', 'erp5_ingestion',
'erp5_trade', 'erp5_crm',
'erp5_knowledge_pad', 'erp5_jquery',
'erp5_accounting', 'erp5_jquery_ui',
'erp5_tax_resource', 'erp5_knowledge_pad',
'erp5_discount_resource', 'erp5_web',
'erp5_invoicing', 'erp5_dms',
'erp5_configurator_standard_categories', 'erp5_l10n_fr',
'erp5_trade_knowledge_pad', 'erp5_content_translation',
'erp5_crm_knowledge_pad', 'erp5_software_pdm',
'erp5_simulation_test', 'erp5_computer_immobilisation',
'erp5_simplified_invoicing', 'erp5_accounting',
'erp5_ods_style', 'erp5_accounting_l10n_fr',
'erp5_odt_style', 'erp5_tax_resource',
'erp5_ooo_import', 'erp5_discount_resource',
'erp5_accounting_l10n_fr', 'erp5_invoicing',
'erp5_l10n_fr', 'erp5_ods_style',
'erp5_l10n_pt-BR', 'erp5_odt_style',
'erp5_demo_maxma_rule') 'erp5_ooo_import',
'erp5_simplified_invoicing',
'erp5_legacy_tax_system',
'erp5_commerce',
'erp5_project',
'erp5_credential',
'erp5_km',
'erp5_web_download_theme',
'vifib_mysql_innodb_catalog',
'vifib_core',
'vifib_base',
'vifib_slap',
'vifib_crm',
'vifib_forge_release',
'vifib_software_pdm',
'vifib_web',
'vifib_open_trade',
'vifib_l10n_fr',
'vifib_datas',
'vifib_erp5')
def getBusinessTemplateList(self): def getBusinessTemplateList(self):
return ('erp5_core_proxy_field_legacy', return ('erp5_core_proxy_field_legacy',
...@@ -72,7 +91,7 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin): ...@@ -72,7 +91,7 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
'erp5_base', 'erp5_base',
'erp5_workflow', 'erp5_workflow',
'erp5_configurator', 'erp5_configurator',
'erp5_configurator_maxma_demo',) 'erp5_configurator_vifib',)
def stepCreateBusinessConfiguration(self, sequence=None,\ def stepCreateBusinessConfiguration(self, sequence=None,\
sequence_list=None, **kw): sequence_list=None, **kw):
...@@ -80,7 +99,7 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin): ...@@ -80,7 +99,7 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
module = self.portal.business_configuration_module module = self.portal.business_configuration_module
business_configuration = module.newContent( business_configuration = module.newContent(
portal_type="Business Configuration", portal_type="Business Configuration",
title='Test Configurator Maxma Demo Workflow') title='Test Configurator Vifib Workflow')
next_dict = {} next_dict = {}
sequence.edit(business_configuration=business_configuration, sequence.edit(business_configuration=business_configuration,
next_dict=next_dict) next_dict=next_dict)
...@@ -94,44 +113,13 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin): ...@@ -94,44 +113,13 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
self.assertEquals('show', response_dict['command']) self.assertEquals('show', response_dict['command'])
self.assertEquals('Install', response_dict['next']) self.assertEquals('Install', response_dict['next'])
def stepSetMaxmaDemoWorkflow(self, sequence=None, sequence_list=None, **kw): def stepSetVifibWorkflow(self, sequence=None, sequence_list=None, **kw):
""" Set Consulting Workflow into Business Configuration """ """ Set Consulting Workflow into Business Configuration """
business_configuration = sequence.get("business_configuration") business_configuration = sequence.get("business_configuration")
self.setBusinessConfigurationWorkflow(business_configuration, self.setBusinessConfigurationWorkflow(business_configuration,
"workflow_module/maxma_demo_configuration_workflow") "workflow_module/vifib_configuration_workflow")
def stepViewCreatedPersons(self, sequence=None, sequence_list=None, **kw):
self.login(user_name='test_configurator_user')
person_list = self.portal.person_module.searchFolder()
self.assertNotEquals(0, len(person_list))
for entity in person_list:
for username in self.all_username_list:
self.failUnlessUserCanAccessDocument(username, entity)
self.failUnlessUserCanViewDocument(username, entity)
def stepViewCreatedOrganisations(self, sequence=None, sequence_list=None, **kw):
self.login(user_name='test_configurator_user')
organisation_list = self.portal.organisation_module.searchFolder()
self.assertNotEquals(0, len(organisation_list))
for entity in organisation_list:
for username in self.all_username_list:
self.failUnlessUserCanAccessDocument(username, entity)
self.failUnlessUserCanViewDocument(username, entity)
def stepViewCreatedAssignemnts(self, sequence=None, sequence_list=None, **kw):
self.login(user_name='test_configurator_user')
person_list = self.portal_person_module.searchFolder()
self.assertNotEquals(0, len(person_list))
for person in person_list:
for assignment in person.contentValues(portal_type='Assignment'):
for username in self.all_username_list:
self.failUnlessUserCanAccessDocument(username, assignment)
self.failUnlessUserCanViewDocument(username, assignment)
def stepCheckMaxmaDemoSampleObjectList(self, sequence=None, sequence_list=None, **kw): def stepCheckMaxmaDemoSampleObjectList(self, sequence=None, sequence_list=None, **kw):
""" Check if objects are placed into the appropriate state """ """ Check if objects are placed into the appropriate state """
...@@ -143,22 +131,11 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin): ...@@ -143,22 +131,11 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
gadget.getValidationState())) gadget.getValidationState()))
gadget.Base_checkConsistency() gadget.Base_checkConsistency()
# Check if demo user is working.
user = self.portal.portal_catalog.getResultValue(portal_type="Person",
reference=self.user_reference)
self.assertNotEquals(user.Person_getAvailableAssignmentValueList(), [])
self.assertEquals(user.getTitle(), "Jack Vale")
self.assertEquals(user.getValidationState(), "validated")
self.assertEquals(user.getSubordination(),
'organisation_module/myorganisation')
self.assertEquals(user.getSubordinationTitle(), "Maxma Co")
### STEPS ### STEPS
DEFAULT_SEQUENCE_LIST = """ DEFAULT_SEQUENCE_LIST = """
stepCreateBusinessConfiguration stepCreateBusinessConfiguration
stepTic stepTic
stepSetMaxmaDemoWorkflow stepSetVifibWorkflow
stepTic stepTic
stepConfiguratorNext stepConfiguratorNext
stepTic stepTic
...@@ -171,61 +148,9 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin): ...@@ -171,61 +148,9 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
stepStartConfigurationInstallation stepStartConfigurationInstallation
stepTic stepTic
stepCheckInstanceIsConfigured%(country)s stepCheckInstanceIsConfigured%(country)s
stepCheckMaxmaDemoSampleObjectList
stepTic
stepViewAddGadget
stepViewEventModule
stepAddEvent
stepSentEventWorkflow
stepViewAccountModule
stepAddAccountModule
stepViewAccount
stepCopyPasteAccount
stepViewEntityModules
stepAddEntityModules
stepCopyAndPastePerson
stepCopyAndPasteOrganisation
stepEntityWorkflow
stepViewCreatedPersons
stepViewCreatedOrganisations
stepViewCreatedAssignemnts
stepAddAccoutingPeriod
stepValidatedAccountingPeriods
stepViewBankAccount
stepViewCreditCard
stepValidateAndModifyBankAccount
stepValidateAndModifyCreditCard
stepAddPaymentNodeInPerson
stepAddPaymentNodeInOrganisation
stepCopyAndPasteBankAccountInPerson
stepCopyAndPasteBankAccountInOrganisation
stepViewAccountingTransactionModule
stepAddAccountingTransactionModule
stepCopyAndPasteAccountingTransactions
stepTic
stepAccountingTransaction
stepTic
stepSaleInvoiceTransaction
stepTic
stepPurchaseInvoiceTransaction
stepTic
stepPaymentTransaction
stepTic
stepBalanceTransaction
stepTic
stepAccountingTransaction_getCausalityGroupedAccountingTransactionList
stepAddAssignments
stepAssignmentTI
stepEditAssignments
stepViewAcessAddPurchaseTradeCondition
stepViewAccessAddSaleTradeCondition
stepViewAccessAddSaleOrder
stepViewAccessAddSalePackingList
stepViewAccessPurchaseOrder
stepPurchasePackingList
""" """
def test_maxma_demo_workflow(self): def test_vifib_workflow(self):
""" Test the consulting workflow configuration""" """ Test the consulting workflow configuration"""
self.all_username_list = ["demo"] self.all_username_list = ["demo"]
self.accountant_username_list = self.all_username_list self.accountant_username_list = self.all_username_list
...@@ -241,5 +166,5 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin): ...@@ -241,5 +166,5 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
import unittest import unittest
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestMaxmaDemoConfiguratorWorkflow)) suite.addTest(unittest.makeSuite(TestVifibConfiguratorWorkflow))
return suite return suite
8 11
\ No newline at end of file \ No newline at end of file
testMaxmaDemoConfigurationWorkflow testVifibConfigurationWorkflow
\ No newline at end of file \ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_action</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>get_certificate</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>Modify portal content</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Action Information</string> </value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>10.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Get Certificate</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/Person_getCertificate</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_action</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>revoke_certificate</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>Modify portal content</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Action Information</string> </value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>11.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Revoke Certificate</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/Person_revokeCertificate</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from AccessControl import ClassSecurityInfo, Unauthorized, getSecurityManager
from Products.ERP5.Document.Person import Person as ERP5Person
class Person(ERP5Person):
security = ClassSecurityInfo()
security.declarePublic('getCertificate')
def _checkCertificateRequest(self):
try:
self.checkUserCanChangePassword()
except Unauthorized:
# in ERP5 user has no SetOwnPassword permission on Person document
# referring himself, so implement "security" by checking that currently
# logged in user is trying to get/revoke his own certificate
reference = self.getReference()
if not reference:
raise
if getSecurityManager().getUser().getId() != reference:
raise
def _getCertificate(self):
return self.getPortalObject().portal_certificate_authority\
.getNewCertificate(self.getReference())
def _revokeCertificate(self):
return self.getPortalObject().portal_certificate_authority\
.revokeCertificateByCommonName(self.getReference())
def getCertificate(self):
"""Returns new SSL certificate"""
self._checkCertificateRequest()
return self._getCertificate()
security.declarePublic('revokeCertificate')
def revokeCertificate(self):
"""Revokes existing certificate"""
self._checkCertificateRequest()
self._revokeCertificate()
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from Products.ERP5.Document.Item import Item from Products.ERP5.Document.Item import Item
from lxml import etree
class SoftwareInstance(Item): class SoftwareInstance(Item):
""" """
...@@ -42,3 +43,20 @@ class SoftwareInstance(Item): ...@@ -42,3 +43,20 @@ class SoftwareInstance(Item):
security.declareObjectProtected(Permissions.AccessContentsInformation) security.declareObjectProtected(Permissions.AccessContentsInformation)
security.declareProtected(Permissions.AccessContentsInformation,
'getSlaXmlAsDict')
def getSlaXmlAsDict(self):
"""Returns SLA XML as python dictionary"""
result_dict = {}
xml = self.getSlaXml()
if xml is not None and xml != '':
tree = etree.fromstring(xml.encode('utf-8'))
for element in tree.findall('parameter'):
key = element.get('id')
value = result_dict.get(key, None)
if value is not None:
value = value + ' ' + element.text
else:
value = element.text
result_dict[key] = value
return result_dict
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>mode</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/text</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>XML Service Level Agreement parameters</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>sla_xml_property</string> </value>
</item>
<item>
<key> <string>mode</string> </key>
<value> <string>w</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>certificate = context.getCertificate()\n
request = context.REQUEST\n
request.set(\'your_certificate\', certificate[\'certificate\'])\n
request.set(\'your_key\', certificate[\'key\'])\n
return context.Person_getCertificateForm()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>dialog_id=None, form_id=None, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Person_getCertificate</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5Form" module="Products.ERP5Form.Form"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>left</string>
<string>right</string>
<string>center</string>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>center</string> </key>
<value>
<list>
<string>your_certificate</string>
<string>your_key</string>
</list>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>left</string> </key>
<value>
<list>
<string>your_tip</string>
</list>
</value>
</item>
<item>
<key> <string>right</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Person_getCertificateForm</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>Person_getCertificateForm</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>form_dialog</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Certificate Request</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>update_action_title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>context.revokeCertificate()\n
return context.Base_redirect(form_id, keep_items = {\'portal_status_message\' : \'Certificate revoked.\'}, **kw)\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>dialog_id=None, form_id=None, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Person_revokeCertificate</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -86,6 +86,7 @@ ...@@ -86,6 +86,7 @@
<string>my_ssl_key</string> <string>my_ssl_key</string>
<string>my_ssl_certificate</string> <string>my_ssl_certificate</string>
<string>my_description</string> <string>my_description</string>
<string>my_sla_xml</string>
</list> </list>
</value> </value>
</item> </item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>editable</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_sla_xml</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_text_area_field</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Service Level Agreement XML</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -68,20 +68,22 @@ sale_packing_list = sale_packing_list_module.newContent(\n ...@@ -68,20 +68,22 @@ sale_packing_list = sale_packing_list_module.newContent(\n
source=instance_setup_sale_packing_list.getSource(),\n source=instance_setup_sale_packing_list.getSource(),\n
source_section=instance_setup_sale_packing_list.getSourceSection(),\n source_section=instance_setup_sale_packing_list.getSourceSection(),\n
price_currency=instance_setup_sale_packing_list.getPriceCurrency(),\n price_currency=instance_setup_sale_packing_list.getPriceCurrency(),\n
start_date=DateTime())\n start_date=DateTime(),\n
activate_kw={\'tag\': tag})\n
\n \n
instance_hosting_sale_packing_list_line = sale_packing_list.newContent(\n instance_hosting_sale_packing_list_line = sale_packing_list.newContent(\n
portal_type=\'Sale Packing List Line\',\n portal_type=\'Sale Packing List Line\',\n
resource=service_relative_url,\n resource=service_relative_url,\n
quantity=instance_setup_sale_packing_list_line.getQuantity(),\n quantity=instance_setup_sale_packing_list_line.getQuantity(),\n
aggregate_list=instance_setup_sale_packing_list_line.getAggregateList(),\n aggregate_list=instance_setup_sale_packing_list_line.getAggregateList(),\n
activate_kw={\'tag\': tag}\n
)\n )\n
return sale_packing_list\n return sale_packing_list\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>state_change, service_relative_url</string> </value> <value> <string>state_change, service_relative_url, tag=None</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
...@@ -61,7 +61,7 @@ hosting_subscription_uid = state_change.kwargs[\'hosting_subscription_uid\']\n ...@@ -61,7 +61,7 @@ hosting_subscription_uid = state_change.kwargs[\'hosting_subscription_uid\']\n
shared = state_change.kwargs[\'shared\']\n shared = state_change.kwargs[\'shared\']\n
software_type = state_change.kwargs["software_type"]\n software_type = state_change.kwargs["software_type"]\n
tag = state_change.kwargs[\'tag\']\n tag = state_change.kwargs[\'tag\']\n
filter_kw = state_change.kwargs["filter_kw"]\n filter_kw = software_instance.getSlaXmlAsDict()\n
\n \n
# Assertion: No packing list line should be related to this software instance\n # Assertion: No packing list line should be related to this software instance\n
packing_list_line = software_instance.getAggregateRelatedValue(portal_type=\'Sale Packing List Line\')\n packing_list_line = software_instance.getAggregateRelatedValue(portal_type=\'Sale Packing List Line\')\n
......
...@@ -50,12 +50,22 @@ ...@@ -50,12 +50,22 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>software_instance = state_change[\'object\']\n <value> <string encoding="cdata"><![CDATA[
software_instance = state_change[\'object\']\n
tag = "%s_destroyInProgress" % software_instance.getUid()\n
portal = context.getPortalObject()\n
if (portal.portal_activities.countMessageWithTag(tag) > 0):\n
raise ValueError("Software Instance is currently being destroyed.")\n
# lock software instance in transaction\n
software_instance.serialize()\n
service_relative_url = software_instance.portal_preferences.\\\n service_relative_url = software_instance.portal_preferences.\\\n
getPreferredInstanceCleanupResource()\n getPreferredInstanceCleanupResource()\n
sale_packing_list = context.SoftwareInstance_createSalePackingList(state_change, service_relative_url)\n sale_packing_list = context.SoftwareInstance_createSalePackingList(state_change, service_relative_url, tag=tag)\n
sale_packing_list.confirm()\n sale_packing_list.confirm(activate_kw={\'tag\':tag})\n
</string> </value>
]]></string> </value>
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
......
...@@ -61,7 +61,7 @@ requested_partition_reference = kwargs["partition_reference"]\n ...@@ -61,7 +61,7 @@ requested_partition_reference = kwargs["partition_reference"]\n
shared = kwargs["shared"]\n shared = kwargs["shared"]\n
software_type = kwargs["software_type"]\n software_type = kwargs["software_type"]\n
instance_xml = kwargs["instance_xml"]\n instance_xml = kwargs["instance_xml"]\n
filter_kw = kwargs["filter_kw"]\n sla_xml = kwargs["sla_xml"]\n
\n \n
# Get root software instance\n # Get root software instance\n
predecessor_software_instance = software_instance\n predecessor_software_instance = software_instance\n
...@@ -97,6 +97,7 @@ if (request_software_instance is None):\n ...@@ -97,6 +97,7 @@ if (request_software_instance is None):\n
title=requested_partition_reference,\n title=requested_partition_reference,\n
source_reference=software_type,\n source_reference=software_type,\n
text_content=instance_xml,\n text_content=instance_xml,\n
sla_xml=sla_xml,\n
activate_kw={\'tag\': tag},\n activate_kw={\'tag\': tag},\n
**portal.Base_getNewSoftwareInstanceCoordinate()\n **portal.Base_getNewSoftwareInstanceCoordinate()\n
)\n )\n
...@@ -108,13 +109,13 @@ if (request_software_instance is None):\n ...@@ -108,13 +109,13 @@ if (request_software_instance is None):\n
hosting_subscription_uid=hosting_subscription_uid,\n hosting_subscription_uid=hosting_subscription_uid,\n
shared=shared,\n shared=shared,\n
software_type=software_type,\n software_type=software_type,\n
tag=tag,\n tag=tag)\n
filter_kw=filter_kw)\n
else:\n else:\n
# Update existing software instance\n # Update existing software instance\n
# Sale Packing List interaction has to be requested automatically with an interaction workflow\n # Sale Packing List interaction has to be requested automatically with an interaction workflow\n
request_software_instance.edit(\n request_software_instance.edit(\n
text_content=instance_xml,\n text_content=instance_xml,\n
sla_xml=sla_xml,\n
activate_kw={\'tag\': tag},\n activate_kw={\'tag\': tag},\n
)\n )\n
# Update the predecessor category of the original caller\n # Update the predecessor category of the original caller\n
......
...@@ -50,7 +50,9 @@ ...@@ -50,7 +50,9 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>software_instance = state_change[\'object\']\n <value> <string encoding="cdata"><![CDATA[
software_instance = state_change[\'object\']\n
service_relative_url = software_instance.portal_preferences.\\\n service_relative_url = software_instance.portal_preferences.\\\n
getPreferredInstanceHostingResource()\n getPreferredInstanceHostingResource()\n
need_to_create_packing_list = False\n need_to_create_packing_list = False\n
...@@ -63,10 +65,18 @@ else:\n ...@@ -63,10 +65,18 @@ else:\n
if sale_packing_list_line.getSimulationState() == \'delivered\':\n if sale_packing_list_line.getSimulationState() == \'delivered\':\n
need_to_create_packing_list = True\n need_to_create_packing_list = True\n
\n \n
portal = context.getPortalObject()\n
if need_to_create_packing_list:\n if need_to_create_packing_list:\n
sale_packing_list = context.SoftwareInstance_createSalePackingList(state_change, service_relative_url)\n tag = "%s_startInProgress" % software_instance.getUid()\n
sale_packing_list.confirm()\n if (portal.portal_activities.countMessageWithTag(tag) > 0):\n
</string> </value> raise ValueError("Software Instance is currently being started.")\n
# lock software instance in transaction\n
software_instance.serialize()\n
sale_packing_list = context.SoftwareInstance_createSalePackingList(state_change, service_relative_url, tag)\n
sale_packing_list.confirm(activate_kw={\'tag\':tag})\n
]]></string> </value>
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
......
230 243
\ No newline at end of file \ No newline at end of file
Person | get_certificate
Person | revoke_certificate
Software Instance Module | view Software Instance Module | view
Software Instance | jump_to_software_instance Software Instance | jump_to_software_instance
Software Instance | view Software Instance | view
\ No newline at end of file
SoftwareInstance SoftwareInstance
\ No newline at end of file Person
\ No newline at end of file
...@@ -41,109 +41,46 @@ class TestVifibCredential(testVifibMixin): ...@@ -41,109 +41,46 @@ class TestVifibCredential(testVifibMixin):
result_list.append("vifib_credential") result_list.append("vifib_credential")
return result_list return result_list
def createCredentialRequest(self, def stepSetCredentialRequestAutomaticApprovalPreferences(self):
first_name="Gabriel", self.setSystemPreference()
last_name="Monnerat", default_system_preference = self.portal.portal_preferences.restrictedTraverse(self.getDefaultSitePreferenceId())
reference="gabriel", self.login("ERP5TypeTestCase")
password="123", default_system_preference.edit(preferred_credential_request_automatic_approval=True)
default_email_text="gabriel@test.com"): self.logout()
def stepValidateNotificationMessage(self):
module = self.portal.notification_message_module
reference = "crendential_request-confirmation-without-password"
search_result = module.searchFolder(reference=reference)
[notification.getObject().validate() for notification in search_result]
def testBase_getDefaultAssignmentArgumentDict(self):
self.stepValidateNotificationMessage()
self.stepSetCredentialRequestAutomaticApprovalPreferences()
self.logout() self.logout()
self.portal.ERP5Site_registerCredentialRequest(first_name=first_name, portal_catalog = self.portal.portal_catalog
last_name=last_name, self.portal.ERP5Site_registerCredentialRequest(first_name="Vifib",
reference=reference, last_name="Test",
password=password, reference="vifib_test",
password="vifib",
career_subordination_title="", career_subordination_title="",
default_email_text=default_email_text, default_email_text="vifib@vifib.com",
default_telephone_text="223344", default_telephone_text="223344",
default_address_street_address="Test Street", default_address_street_address="Test Street",
default_address_city="Campos", default_address_city="My Street",
default_address_zip_code="28024030") default_address_zip_code="28024030")
self.login("ERP5TypeTestCase") self.login("ERP5TypeTestCase")
self.stepTic() self.stepTic()
credential_request = portal_catalog.getResultValue(portal_type="Credential Request",
def createSystemPreference(self): reference="vifib_test")
""" """
portal_preferences = self.getPreferenceTool()
preference = portal_preferences.newContent(portal_type='System Preference',
title='Default Site Preference',
id='test_site_preference')
self.stepTic()
return preference
def afterSetUp(self):
""" """
portal_preferences = self.getPreferenceTool()
preference = getattr(portal_preferences, 'test_site_preference', None)
if preference is None:
preference = self.createSystemPreference()
if preference.getPreferenceState() == 'disabled':
preference.enable()
preference.edit(preferred_credential_request_automatic_approval=True,
preferred_credential_recovery_automatic_approval=True,
preferred_organisation_credential_update_automatic_approval=True,
preferred_person_credential_update_automatic_approval=True)
self.portal.email_from_address = 'site@example.invalid'
oldMailHost = getattr(self.portal, 'MailHost', None)
if oldMailHost is not None:
self.portal.manage_delObjects(['MailHost'])
self.portal._setObject('MailHost', DummyMailHost('MailHost'))
self.stepTic()
def testMailMessagePosted(self):
""" Test if the Mail Message was posted correctly """
self.createCredentialRequest(reference="vifibtest")
portal_catalog = self.portal.portal_catalog
credential_request = portal_catalog.getResultValue(portal_type="Credential Request",
reference="vifibtest")
mail_message = portal_catalog.getResultValue(portal_type="Mail Message",
follow_up=credential_request)
self.assertEquals(mail_message.getSimulationState(), "started")
self.assertTrue("key=%s" % mail_message.getReference() in mail_message.getTextContent())
def test_MailFromMailMessageEvent(self):
""" """
self.createCredentialRequest(first_name="Vifib",
last_name="Test",
reference="vifibtest")
portal_catalog = self.portal.portal_catalog
credential_request = portal_catalog.getResultValue(portal_type="Credential Request",
reference="vifibtest",
first_name="Vifib",
last_name="Test")
mail_message = portal_catalog.getResultValue(portal_type="Mail Message",
follow_up=credential_request)
last_message = self.portal.MailHost._last_message
self.assertNotEquals((), last_message)
mfrom, mto, message_text = last_message
self.assertEquals(mfrom, 'Portal Administrator <site@example.invalid>')
self.assertEquals(['Vifib Test <gabriel@test.com>'], mto)
self.assertNotEquals(re.search("Subject\:.*Welcome_to_Vifib", message_text), None)
self.assertNotEquals(re.search("Hello\ Vifib\ Test\,", message_text), None)
self.assertNotEquals(re.search("key\=..%s" % mail_message.getReference(), message_text), None)
def testERP5Site_activeLogin(self):
""" Test if the script WebSection_activeLogin will create one user
correctly """
self.createCredentialRequest()
portal_catalog = self.portal.portal_catalog
credential_request = portal_catalog.getResultValue(portal_type="Credential Request",
reference="gabriel")
mail_message = portal_catalog.getResultValue(portal_type="Mail Message", mail_message = portal_catalog.getResultValue(portal_type="Mail Message",
follow_up=credential_request) follow_up=credential_request)
self.logout() self.logout()
self.portal.ERP5Site_activeLogin(mail_message.getReference()) self.portal.ERP5Site_activeLogin(mail_message.getReference())
self.login("ERP5TypeTestCase") self.login("ERP5TypeTestCase")
self.stepTic() self.stepTic()
person = portal_catalog.getResultValue(reference="gabriel", portal_type="Person") person = portal_catalog.getResultValue(reference="vifib_test", portal_type="Person")
self.assertEquals(person.getValidationState(), "validated") assignment_list = person.objectValues(portal_type="Assignment")
assignment = assignment_list[0]
def testERP5Site_registerCredentialRequest(self): self.assertEquals(assignment.getFunction(), "customer")
""" Test if the script ERP5Site_registerCredentialRequest will create one self.assertEquals(assignment.getRole(), "client")
Credential Request correctly """
self.createCredentialRequest()
portal_catalog = self.portal.portal_catalog
credential_request = portal_catalog.getResultValue(portal_type="Credential Request",
reference="gabriel")
self.assertEquals(credential_request.getFirstName(), "Gabriel")
self.assertEquals(credential_request.getDefaultEmailText(), "gabriel@test.com")
27 28
\ No newline at end of file \ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="TradeModelPath" module="Products.ERP5Type.Document.TradeModelPath"/> <global name="Trade Model Path" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="Computer" module="Products.ERP5Type.Document.Computer"/> <global name="Computer" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="ComputerPartition" module="Products.ERP5Type.Document.ComputerPartition"/> <global name="Computer Partition" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="Supply" module="Products.ERP5Type.Document.Supply"/> <global name="Open Sale Order" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="SupplyLine" module="Products.ERP5Type.Document.SupplyLine"/> <global name="Open Sale Order Line" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="Organisation" module="Products.ERP5Type.Document.Organisation"/> <global name="Organisation" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="Organisation" module="Products.ERP5Type.Document.Organisation"/> <global name="Organisation" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="AccountingTransaction" module="Products.ERP5Type.Document.AccountingTransaction"/> <global name="Accounting Period" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="GeographicAddress" module="Products.ERP5Type.Document.GeographicAddress"/> <global name="Address" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="Url" module="Products.ERP5Type.Document.Url"/> <global name="Email" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="Telephone" module="Products.ERP5Type.Document.Telephone"/> <global name="Telephone" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="SubscriptionItemRootSimulationRule" module="Products.ERP5Type.Document.SubscriptionItemRootSimulationRule"/> <global name="Subscription Item Root Simulation Rule" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="FloatEquivalenceTester" module="Products.ERP5Type.Document.FloatEquivalenceTester"/> <global name="Float Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="NetConvertedQuantityEquivalenceTester" module="Products.ERP5Type.Document.NetConvertedQuantityEquivalenceTester"/> <global name="Net Converted Quantity Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/> <global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="DateTimeEquivalenceTester" module="Products.ERP5Type.Document.DateTimeEquivalenceTester"/> <global name="DateTime Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="DateTimeEquivalenceTester" module="Products.ERP5Type.Document.DateTimeEquivalenceTester"/> <global name="DateTime Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="VariationEquivalenceTester" module="Products.ERP5Type.Document.VariationEquivalenceTester"/> <global name="Variation Divergence Tester" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="PackingList" module="Products.ERP5Type.Document.PackingList"/> <global name="Purchase Packing List" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="DeliveryLine" module="Products.ERP5Type.Document.DeliveryLine"/> <global name="Purchase Packing List Line" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="TradeCondition" module="Products.ERP5Type.Document.TradeCondition"/> <global name="Sale Trade Condition" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="TradeCondition" module="Products.ERP5Type.Document.TradeCondition"/> <global name="Sale Trade Condition" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="SoftwareProduct" module="Products.ERP5Type.Document.SoftwareProduct"/> <global name="Software Product" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
<key> <string>_Access_contents_information_Permission</string> </key> <key> <string>_Access_contents_information_Permission</string> </key>
<value> <value>
<tuple> <tuple>
<string>Anonymous</string>
<string>Assignee</string> <string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
...@@ -44,6 +45,7 @@ ...@@ -44,6 +45,7 @@
<key> <string>_View_Permission</string> </key> <key> <string>_View_Permission</string> </key>
<value> <value>
<tuple> <tuple>
<string>Anonymous</string>
<string>Assignee</string> <string>Assignee</string>
<string>Assignor</string> <string>Assignor</string>
<string>Associate</string> <string>Associate</string>
...@@ -84,7 +86,127 @@ ...@@ -84,7 +86,127 @@
<key> <string>title</string> </key> <key> <string>title</string> </key>
<value> <string>test_software_product</string> </value> <value> <string>test_software_product</string> </value>
</item> </item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>commerce_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
</pickle>
<pickle>
<tuple>
<none/>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>publish_action</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global id="3.1" name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1307981928.46</float>
<string>GMT+2</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>draft</string> </value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>publish</string> </value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass> <reference id="3.1"/> </klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1307981928.46</float>
<string>GMT+2</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>published</string> </value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
</record>
</ZopeData> </ZopeData>
...@@ -66,13 +66,16 @@ for order_line in order.getMovementList():\n ...@@ -66,13 +66,16 @@ for order_line in order.getMovementList():\n
computer_partition = None\n computer_partition = None\n
\n \n
# XXX Duplicated from request method...\n # XXX Duplicated from request method...\n
\n
query_kw = {\n query_kw = {\n
\'software_release_url\': software_release.getUrlString(),\n \'software_release_url\': software_release.getUrlString(),\n
\'portal_type\': \'Computer Partition\',\n \'portal_type\': \'Computer Partition\',\n
# \'relative_url\': \'computer_module/20110126-E2AE/%\',\n # \'relative_url\': \'computer_module/20110126-E2AE/%\',\n
\'free_for_request\': 1,\n \'free_for_request\': 1,\n
}\n }\n
# support SLA\n
filter_kw = software_instance.getSlaXmlAsDict()\n
if "computer_guid" in filter_kw:\n
query_kw["parent_reference"] = filter_kw["computer_guid"]\n
\n \n
result_count = software_instance.portal_catalog.countResults(**query_kw)[0][0]\n result_count = software_instance.portal_catalog.countResults(**query_kw)[0][0]\n
offset = max(0, result_count-1)\n offset = max(0, result_count-1)\n
......
85 88
\ No newline at end of file \ No newline at end of file
software_release_module/test_software_release software_release_module/test_software_release
\ No newline at end of file software_product_module/test_software_product
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="Alarm" module="Products.ERP5Type.Document.Alarm"/> <global name="Alarm" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
</item> </item>
<item> <item>
<key> <string>type_class</string> </key> <key> <string>type_class</string> </key>
<value> <string>Folder</string> </value> <value> <string>Products.Vifib.Tool.SlapTool.SlapTool</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="SlapTool" module="Products.Vifib.Tool.SlapTool"/> <global name="Slap Tool" module="erp5.portal_type"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
......
...@@ -59,8 +59,9 @@ portal = person.getPortalObject()\n ...@@ -59,8 +59,9 @@ portal = person.getPortalObject()\n
kwargs = state_change.kwargs\n kwargs = state_change.kwargs\n
software_release_url_string = state_change.kwargs[\'software_release\']\n software_release_url_string = state_change.kwargs[\'software_release\']\n
software_title = kwargs["software_title"]\n software_title = kwargs["software_title"]\n
software_type = "RootSoftwareInstance"\n software_type = kwargs.get("software_type") or "RootSoftwareInstance"\n
instance_xml = kwargs["instance_xml"]\n instance_xml = kwargs["instance_xml"]\n
sla_xml = kwargs.get("sla_xml") or ""\n
\n \n
sale_order_portal_type = "Sale Order"\n sale_order_portal_type = "Sale Order"\n
sale_order_line_portal_type = "Sale Order Line"\n sale_order_line_portal_type = "Sale Order Line"\n
...@@ -96,6 +97,7 @@ if (request_software_instance is None):\n ...@@ -96,6 +97,7 @@ if (request_software_instance is None):\n
source_reference=software_type,\n source_reference=software_type,\n
title=software_title,\n title=software_title,\n
text_content=instance_xml,\n text_content=instance_xml,\n
sla_xml=sla_xml,\n
activate_kw={\'tag\': tag},\n activate_kw={\'tag\': tag},\n
**portal.Base_getNewSoftwareInstanceCoordinate()\n **portal.Base_getNewSoftwareInstanceCoordinate()\n
)\n )\n
...@@ -168,6 +170,7 @@ else:\n ...@@ -168,6 +170,7 @@ else:\n
# Update existing software instance\n # Update existing software instance\n
request_software_instance.edit(\n request_software_instance.edit(\n
text_content=instance_xml,\n text_content=instance_xml,\n
sla_xml=sla_xml,\n
activate_kw={\'tag\': tag},\n activate_kw={\'tag\': tag},\n
)\n )\n
......
372 378
\ No newline at end of file \ No newline at end of file
...@@ -180,7 +180,8 @@ class CertificateAuthorityTool(BaseTool): ...@@ -180,7 +180,8 @@ class CertificateAuthorityTool(BaseTool):
security.declareProtected(Permissions.AccessContentsInformation, 'getNewCertificate') security.declareProtected(Permissions.AccessContentsInformation, 'getNewCertificate')
def getNewCertificate(self, common_name): def getNewCertificate(self, common_name):
"""Returns certificate for passed common name, as dictionary of {key, certificate, id, common_name}""" # No docstring in order to make this method non publishable
# Returns certificate for passed common name, as dictionary of {key, certificate, id, common_name}
self._checkCertificateAuthority() self._checkCertificateAuthority()
self._lockCertificateAuthority() self._lockCertificateAuthority()
try: try:
...@@ -215,7 +216,8 @@ class CertificateAuthorityTool(BaseTool): ...@@ -215,7 +216,8 @@ class CertificateAuthorityTool(BaseTool):
security.declareProtected(Permissions.AccessContentsInformation, 'revokeCertificate') security.declareProtected(Permissions.AccessContentsInformation, 'revokeCertificate')
def revokeCertificate(self, serial): def revokeCertificate(self, serial):
"""Revokes certificate with serial, returns dictionary {crl}""" # No docstring in order to make this method non publishable
# Revokes certificate with serial, returns dictionary {crl}
self._checkCertificateAuthority() self._checkCertificateAuthority()
self._lockCertificateAuthority() self._lockCertificateAuthority()
try: try:
...@@ -247,4 +249,19 @@ class CertificateAuthorityTool(BaseTool): ...@@ -247,4 +249,19 @@ class CertificateAuthorityTool(BaseTool):
finally: finally:
self._unlockCertificateAuthority() self._unlockCertificateAuthority()
def _getValidSerial(self, common_name):
index = open(self.index).read().splitlines()
valid_line_list = [q for q in index if q.startswith('V') and
('CN=%s' % common_name in q)]
if len(valid_line_list) != 1:
raise ValueError('No certificate for %r' % common_name)
return valid_line_list[0].split('\t')[3]
security.declareProtected(Permissions.AccessContentsInformation,
'revokeCertificate')
def revokeCertificateByCommonName(self, common_name):
self._checkCertificateAuthority()
serial = self._getValidSerial(common_name)
self.revokeCertificate(serial)
InitializeClass(CertificateAuthorityTool) InitializeClass(CertificateAuthorityTool)
This diff is collapsed.
...@@ -47,6 +47,7 @@ from Products.ERP5Security.ERP5GroupManager import ConsistencyError, NO_CACHE_MO ...@@ -47,6 +47,7 @@ from Products.ERP5Security.ERP5GroupManager import ConsistencyError, NO_CACHE_MO
from Products.ERP5Type.ERP5Type \ from Products.ERP5Type.ERP5Type \
import ERP5TYPE_SECURITY_GROUP_ID_GENERATION_SCRIPT import ERP5TYPE_SECURITY_GROUP_ID_GENERATION_SCRIPT
from Products.ERP5Type.Cache import CachingMethod from Products.ERP5Type.Cache import CachingMethod
from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery
#Form for new plugin in ZMI #Form for new plugin in ZMI
manage_addVifibMachineAuthenticationPluginForm = PageTemplateFile( manage_addVifibMachineAuthenticationPluginForm = PageTemplateFile(
...@@ -70,11 +71,14 @@ def addVifibMachineAuthenticationPlugin(dispatcher, id, title=None, REQUEST=None ...@@ -70,11 +71,14 @@ def addVifibMachineAuthenticationPlugin(dispatcher, id, title=None, REQUEST=None
def getUserByLogin(portal, login): def getUserByLogin(portal, login):
if isinstance(login, basestring): if isinstance(login, basestring):
login = login, login = login,
result = portal.portal_catalog.unrestrictedSearchResults( machine_query = Query(portal_type=["Computer", "Software Instance"],
select_expression='reference',
portal_type=["Computer", "Software Instance"],
validation_state="validated", validation_state="validated",
reference=dict(query=login, key='ExactMatch')) reference=dict(query=login, key='ExactMatch'))
person_query = Query(portal_type=["Person"],
reference=dict(query=login, key='ExactMatch'))
result = portal.portal_catalog.unrestrictedSearchResults(
query=ComplexQuery(machine_query, person_query, operator="OR"),
select_expression='reference')
# XXX: Here, we filter catalog result list ALTHOUGH we did pass # XXX: Here, we filter catalog result list ALTHOUGH we did pass
# parameters to unrestrictedSearchResults to restrict result set. # parameters to unrestrictedSearchResults to restrict result set.
# This is done because the following values can match person with # This is done because the following values can match person with
...@@ -92,7 +96,6 @@ def getUserByLogin(portal, login): ...@@ -92,7 +96,6 @@ def getUserByLogin(portal, login):
# by default (feature). # by default (feature).
return [x.getObject() for x in result if x['reference'] in login] return [x.getObject() for x in result if x['reference'] in login]
class VifibMachineAuthenticationPlugin(BasePlugin): class VifibMachineAuthenticationPlugin(BasePlugin):
""" """
Plugin to authenicate as machines. Plugin to authenicate as machines.
......
...@@ -2,7 +2,7 @@ from setuptools import setup, find_packages ...@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
import glob import glob
import os import os
version = '0.3-dev' version = '0.4-dev'
name = 'slapos.core' name = 'slapos.core'
long_description = open("README.txt").read() + "\n" + \ long_description = open("README.txt").read() + "\n" + \
open("CHANGES.txt").read() + "\n" open("CHANGES.txt").read() + "\n"
...@@ -33,7 +33,7 @@ setup(name=name, ...@@ -33,7 +33,7 @@ setup(name=name,
install_requires=[ install_requires=[
'Flask', # used by proxy 'Flask', # used by proxy
'lxml', # needed to play with XML trees 'lxml', # needed to play with XML trees
'netaddr', # to play safely with IPv6 prefixes 'netaddr>=0.7.5', # to play safely with IPv6 prefixes
'netifaces', # to fetch information about network devices 'netifaces', # to fetch information about network devices
'setuptools', # namespaces 'setuptools', # namespaces
'supervisor', # slapgrid uses supervisor to manage processes 'supervisor', # slapgrid uses supervisor to manage processes
......
...@@ -18,4 +18,5 @@ ipv4_local_network = 10.0.0.0/16 ...@@ -18,4 +18,5 @@ ipv4_local_network = 10.0.0.0/16
[slapproxy] [slapproxy]
host = 127.0.0.1 host = 127.0.0.1
port = 5000 port = 5000
database_uri = :memory: # or /path/to/file # You could also specify: /path/to/file
database_uri = :memory:
libnetworkcache
===============
The goal of libnetworkcache python library is to abstract the REST calls.
It works as wrapper of python httplib to use the Networkcache HTTP Server.
API
---
So, it must provide 2 methods:
put(file)
''' Upload the file to Networkcache HTTP Server using PUT as HTTP method.'''
get(key)
''' Download the file from Networkcache HTTP Server using GET as HTTP method.'''
...@@ -27,13 +27,13 @@ ...@@ -27,13 +27,13 @@
############################################################################## ##############################################################################
from optparse import OptionParser, Option from optparse import OptionParser, Option
from xml_marshaller import xml_marshaller from xml_marshaller import xml_marshaller
from pwd import getpwnam
import ConfigParser import ConfigParser
import grp import grp
import logging import logging
import netaddr import netaddr
import netifaces import netifaces
import os import os
import pwd
import random import random
import slapos.slap as slap import slapos.slap as slap
import socket import socket
...@@ -41,6 +41,34 @@ import subprocess ...@@ -41,6 +41,34 @@ import subprocess
import sys import sys
import time import time
class OS(object):
_os = os
def __init__(self, config):
self._dry_run = config.dry_run
self._verbose = config.verbose
self._logger = config.logger
add = self._addWrapper
add('chown')
add('chmod')
add('makedirs')
add('mkdir')
def _addWrapper(self, name):
def wrapper(*args, **kw):
if self._verbose:
arg_list = [repr(x) for x in args] + [
'%s=%r' % (x, y) for x, y in kw.iteritems()]
self._logger.debug('%s(%s)' % (
name,
', '.join(arg_list)
))
if not self._dry_run:
getattr(self._os, name)(*args, **kw)
setattr(self, name, wrapper)
def __getattr__(self, name):
return getattr(self._os, name)
class SlapError(Exception): class SlapError(Exception):
""" """
...@@ -195,6 +223,8 @@ class Computer: ...@@ -195,6 +223,8 @@ class Computer:
slap_instance.initializeConnection(config.master_url, slap_instance.initializeConnection(config.master_url,
**connection_dict) **connection_dict)
slap_computer = slap_instance.registerComputer(self.reference) slap_computer = slap_instance.registerComputer(self.reference)
if config.dry_run:
return
return slap_computer.updateConfiguration( return slap_computer.updateConfiguration(
xml_marshaller.dumps(_getDict(self))) xml_marshaller.dumps(_getDict(self)))
...@@ -280,7 +310,7 @@ class Computer: ...@@ -280,7 +310,7 @@ class Computer:
slapsoft.path = self.software_root slapsoft.path = self.software_root
if alter_user: if alter_user:
slapsoft.create() slapsoft.create()
slapsoft_pw = pwd.getpwnam(slapsoft.name) slapsoft_pw = getpwnam(slapsoft.name)
os.chown(self.software_root, slapsoft_pw.pw_uid, slapsoft_pw.pw_gid) os.chown(self.software_root, slapsoft_pw.pw_uid, slapsoft_pw.pw_gid)
os.chmod(self.software_root, 0755) os.chmod(self.software_root, 0755)
...@@ -365,7 +395,7 @@ class Partition: ...@@ -365,7 +395,7 @@ class Partition:
if not os.path.exists(self.path): if not os.path.exists(self.path):
os.mkdir(self.path, 0750) os.mkdir(self.path, 0750)
if alter_user: if alter_user:
owner_pw = pwd.getpwnam(owner.name) owner_pw = getpwnam(owner.name)
os.chown(self.path, owner_pw.pw_uid, owner_pw.pw_gid) os.chown(self.path, owner_pw.pw_uid, owner_pw.pw_gid)
os.chmod(self.path, 0750) os.chmod(self.path, 0750)
...@@ -402,12 +432,12 @@ class User: ...@@ -402,12 +432,12 @@ class User:
except KeyError: except KeyError:
callAndRead(['groupadd', self.name]) callAndRead(['groupadd', self.name])
user_parameter_list = ['-d', self.path, '-g', self.name] user_parameter_list = ['-d', self.path, '-g', self.name, '-s', '/bin/false']
if self.additional_group_list is not None: if self.additional_group_list is not None:
user_parameter_list.extend(['-G', ','.join(self.additional_group_list)]) user_parameter_list.extend(['-G', ','.join(self.additional_group_list)])
user_parameter_list.append(self.name) user_parameter_list.append(self.name)
try: try:
pwd.getpwnam(self.name) getpwnam(self.name)
except KeyError: except KeyError:
callAndRead(['useradd'] + user_parameter_list) callAndRead(['useradd'] + user_parameter_list)
else: else:
...@@ -425,7 +455,7 @@ class User: ...@@ -425,7 +455,7 @@ class User:
""" """
try: try:
pwd.getpwnam(self.name) getpwnam(self.name)
return True return True
except KeyError: except KeyError:
...@@ -463,7 +493,7 @@ class Tap: ...@@ -463,7 +493,7 @@ class Tap:
owner_id = int(open(check_file).read().strip()) owner_id = int(open(check_file).read().strip())
except Exception: except Exception:
pass pass
if (owner_id is None) or (owner_id != pwd.getpwnam(owner.name).pw_uid): if (owner_id is None) or (owner_id != getpwnam(owner.name).pw_uid):
callAndRead(['tunctl', '-t', self.name, '-u', owner.name]) callAndRead(['tunctl', '-t', self.name, '-u', owner.name])
callAndRead(['ip', 'link', 'set', self.name, 'up']) callAndRead(['ip', 'link', 'set', self.name, 'up'])
...@@ -707,6 +737,10 @@ class Parser(OptionParser): ...@@ -707,6 +737,10 @@ class Parser(OptionParser):
help="Shall slapformat alter user database [default: True]"), help="Shall slapformat alter user database [default: True]"),
Option('--alter_network', choices=['True', 'False'], Option('--alter_network', choices=['True', 'False'],
help="Shall slapformat alter network configuration [default: True]"), help="Shall slapformat alter network configuration [default: True]"),
Option("-d", "--dry-run",
default=False,
action="store_true",
help="Don't actually do anything."),
]) ])
def check_args(self): def check_args(self):
...@@ -831,7 +865,8 @@ def run(config): ...@@ -831,7 +865,8 @@ def run(config):
alter_network=config.alter_network) alter_network=config.alter_network)
# Dumping and sending to the erp5 the current configuration # Dumping and sending to the erp5 the current configuration
computer.dump(config.computer_xml) if not config.dry_run:
computer.dump(config.computer_xml)
config.logger.info('Posting information to %r' % config.master_url) config.logger.info('Posting information to %r' % config.master_url)
computer.send(config) computer.send(config)
except: except:
...@@ -904,11 +939,17 @@ class Config: ...@@ -904,11 +939,17 @@ class Config:
self.logger.error(message) self.logger.error(message)
raise UsageError(message) raise UsageError(message)
if self.alter_user: if not self.dry_run:
self.checkRequiredBinary(['groupadd', 'useradd', 'usermod']) if self.alter_user:
self.checkRequiredBinary(['groupadd', 'useradd', 'usermod'])
if self.alter_network:
self.checkRequiredBinary(['ip', 'tunctl'])
# Required, even for dry run
if self.alter_network: if self.alter_network:
self.checkRequiredBinary(['brctl', 'ip', 'tunctl']) self.checkRequiredBinary(['brctl'])
if self.dry_run:
root_needed = False
# check root # check root
if root_needed and os.getuid() != 0: if root_needed and os.getuid() != 0:
...@@ -937,6 +978,8 @@ class Config: ...@@ -937,6 +978,8 @@ class Config:
if self.verbose: if self.verbose:
self.logger.setLevel(logging.DEBUG) self.logger.setLevel(logging.DEBUG)
self.logger.debug("Verbose mode enabled.") self.logger.debug("Verbose mode enabled.")
if self.dry_run:
self.logger.info("Dry-run mode enabled.")
# Calculate path once # Calculate path once
self.computer_xml = os.path.abspath(self.computer_xml) self.computer_xml = os.path.abspath(self.computer_xml)
...@@ -944,6 +987,10 @@ class Config: ...@@ -944,6 +987,10 @@ class Config:
def main(): def main():
"Run default configuration." "Run default configuration."
global os
global callAndRead
global getpwnam
real_callAndRead = callAndRead
usage = "usage: %s [options] CONFIGURATION_FILE" % sys.argv[0] usage = "usage: %s [options] CONFIGURATION_FILE" % sys.argv[0]
try: try:
...@@ -951,6 +998,33 @@ def main(): ...@@ -951,6 +998,33 @@ def main():
options, configuration_file_path = Parser(usage=usage).check_args() options, configuration_file_path = Parser(usage=usage).check_args()
config = Config() config = Config()
config.setConfig(options, configuration_file_path) config.setConfig(options, configuration_file_path)
os = OS(config)
if config.dry_run:
def dry_callAndRead(argument_list, raise_on_error=True):
if argument_list == ['brctl', 'show']:
return real_callAndRead(argument_list, raise_on_error)
else:
return 0, ''
callAndRead = dry_callAndRead
real_addSystemAddress = Bridge._addSystemAddress
def fake_addSystemAddress(*args, **kw):
real_addSystemAddress(*args, **kw)
# Fake success
return True
Bridge._addSystemAddress = fake_addSystemAddress
def fake_getpwnam(user):
class result:
pw_uid = 12345
pw_gid = 54321
return result
getpwnam = fake_getpwnam
else:
dry_callAndRead = real_callAndRead
if config.verbose:
def logging_callAndRead(argument_list, raise_on_error=True):
config.logger.debug(' '.join(argument_list))
return dry_callAndRead(argument_list, raise_on_error)
callAndRead = logging_callAndRead
run(config) run(config)
except UsageError, err: except UsageError, err:
print >>sys.stderr, err.msg print >>sys.stderr, err.msg
......
##############################################################################
#
# Copyright (c) 2010 ViFiB SARL and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
import httplib
import os
class NetworkcacheClient(object):
'''
NetworkcacheClient is a wrapper for httplib.
It must implement all the required methods to use the Networkcache HTTP
Server.
- put(file)
- get(key)
'''
def __init__(self, networkcache_url):
# XXX (lucas): Is it required to check if networkcache_url is a valid URL?
self.networkcache_url = networkcache_url
def _start(self):
self.connection = httplib.HTTPConnection(self.networkcache_url)
def _close(self):
self.connection.close()
def put(self, file_content):
'''
Upload the file to the server.
It uses http PUT resquest method.
'''
if file_content is not None:
raise ValueError('File content should not be None.')
self._start()
try:
self.connection.request('PUT', '/', file_content)
result = self.connection.getresponse()
finally:
self._close()
return result
def get(self, key):
'''
Download the file.
It uses http GET request method.
'''
path_info = '/%s' % key
self._start()
try:
self.connection.request('GET', path_info)
result = self.connection.getresponse()
finally:
self._close()
return result
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