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
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)
================
......
......@@ -55,27 +55,6 @@ from AccessControl import getSecurityManager\n
from Products.ERP5Type.Log import log\n
\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
if gadget.getValidationState() == \'invisible\':\n
gadget.visible()\n
......
......@@ -95,10 +95,10 @@ bt5_installation_list = ( \n
\'vifib_crm\', \n
\'vifib_forge_release\', \n
\'vifib_software_pdm\', \n
\'vifib_web\', \n
\'vifib_web\',\n
\'vifib_open_trade\', \n
\'vifib_l10n_fr\'\n
\'vifib_datas\'\n
\'vifib_l10n_fr\',\n
\'vifib_datas\',\n
\'vifib_erp5\'\n
)\n
\n
......
......@@ -29,42 +29,61 @@ from Products.ERP5Configurator.tests.ConfiguratorTestMixin import \
TestLiveConfiguratorWorkflowMixin
from Products.ERP5Type.tests.Sequence import SequenceList
class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
class TestVifibConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
"""
Configurator Mixin Class
"""
# The list of standard business templates that the configurator should force
# to install
user_reference = "demo"
standard_bt5_list = ('erp5_simulation',
'erp5_dhtml_style',
'erp5_jquery',
'erp5_jquery_ui',
'erp5_xhtml_jquery_style',
standard_bt5_list = (
'erp5_simulation',
'erp5_administration',
'erp5_pdm',
'erp5_trade',
'erp5_simulation_test',
'erp5_item',
'erp5_open_trade',
'erp5_forge',
'erp5_ingestion_mysql_innodb_catalog',
'erp5_ingestion',
'erp5_web',
'erp5_dms',
'erp5_crm',
'erp5_pdm',
'erp5_trade',
'erp5_jquery',
'erp5_jquery_ui',
'erp5_knowledge_pad',
'erp5_web',
'erp5_dms',
'erp5_l10n_fr',
'erp5_content_translation',
'erp5_software_pdm',
'erp5_computer_immobilisation',
'erp5_accounting',
'erp5_accounting_l10n_fr',
'erp5_tax_resource',
'erp5_discount_resource',
'erp5_invoicing',
'erp5_configurator_standard_categories',
'erp5_trade_knowledge_pad',
'erp5_crm_knowledge_pad',
'erp5_simulation_test',
'erp5_simplified_invoicing',
'erp5_ods_style',
'erp5_odt_style',
'erp5_ooo_import',
'erp5_accounting_l10n_fr',
'erp5_l10n_fr',
'erp5_l10n_pt-BR',
'erp5_demo_maxma_rule')
'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):
return ('erp5_core_proxy_field_legacy',
......@@ -72,7 +91,7 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
'erp5_base',
'erp5_workflow',
'erp5_configurator',
'erp5_configurator_maxma_demo',)
'erp5_configurator_vifib',)
def stepCreateBusinessConfiguration(self, sequence=None,\
sequence_list=None, **kw):
......@@ -80,7 +99,7 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
module = self.portal.business_configuration_module
business_configuration = module.newContent(
portal_type="Business Configuration",
title='Test Configurator Maxma Demo Workflow')
title='Test Configurator Vifib Workflow')
next_dict = {}
sequence.edit(business_configuration=business_configuration,
next_dict=next_dict)
......@@ -94,43 +113,12 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
self.assertEquals('show', response_dict['command'])
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 """
business_configuration = sequence.get("business_configuration")
self.setBusinessConfigurationWorkflow(business_configuration,
"workflow_module/maxma_demo_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)
"workflow_module/vifib_configuration_workflow")
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):
......@@ -143,22 +131,11 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
gadget.getValidationState()))
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
DEFAULT_SEQUENCE_LIST = """
stepCreateBusinessConfiguration
stepTic
stepSetMaxmaDemoWorkflow
stepSetVifibWorkflow
stepTic
stepConfiguratorNext
stepTic
......@@ -171,61 +148,9 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
stepStartConfigurationInstallation
stepTic
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"""
self.all_username_list = ["demo"]
self.accountant_username_list = self.all_username_list
......@@ -241,5 +166,5 @@ class TestMaxmaDemoConfiguratorWorkflow(TestLiveConfiguratorWorkflowMixin):
import unittest
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestMaxmaDemoConfiguratorWorkflow))
suite.addTest(unittest.makeSuite(TestVifibConfiguratorWorkflow))
return suite
8
\ No newline at end of file
11
\ No newline at end of file
testMaxmaDemoConfigurationWorkflow
\ No newline at end of file
testVifibConfigurationWorkflow
\ 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 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions
from Products.ERP5.Document.Item import Item
from lxml import etree
class SoftwareInstance(Item):
"""
......@@ -42,3 +43,20 @@ class SoftwareInstance(Item):
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="TextAreaField" module="Products.Formulator.StandardFields"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>your_certificate</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>
<item>
<key> <string>line_too_long</string> </key>
<value> <string>A line was too long.</string> </value>
</item>
<item>
<key> <string>required_not_found</string> </key>
<value> <string>Input is required but no input given.</string> </value>
</item>
<item>
<key> <string>too_long</string> </key>
<value> <string>You entered too many characters.</string> </value>
</item>
<item>
<key> <string>too_many_lines</string> </key>
<value> <string>You entered too many lines.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>5</int> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Certificate</string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>40</int> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="TextAreaField" module="Products.Formulator.StandardFields"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>your_key</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>
<item>
<key> <string>line_too_long</string> </key>
<value> <string>A line was too long.</string> </value>
</item>
<item>
<key> <string>required_not_found</string> </key>
<value> <string>Input is required but no input given.</string> </value>
</item>
<item>
<key> <string>too_long</string> </key>
<value> <string>You entered too many characters.</string> </value>
</item>
<item>
<key> <string>too_many_lines</string> </key>
<value> <string>You entered too many lines.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>5</int> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Key</string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>40</int> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="TextAreaField" module="Products.Formulator.StandardFields"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>your_tip</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>
<item>
<key> <string>line_too_long</string> </key>
<value> <string>A line was too long.</string> </value>
</item>
<item>
<key> <string>required_not_found</string> </key>
<value> <string>Input is required but no input given.</string> </value>
</item>
<item>
<key> <string>too_long</string> </key>
<value> <string>You entered too many characters.</string> </value>
</item>
<item>
<key> <string>too_many_lines</string> </key>
<value> <string>You entered too many lines.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string>Please copy both key and certificate.\n
\n
They are NOT stored anywhere for security reason.</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>height</string> </key>
<value> <int>5</int> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>max_length</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_linelength</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>max_lines</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>required</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Information</string> </value>
</item>
<item>
<key> <string>unicode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>whitespace_preserve</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>width</string> </key>
<value> <int>40</int> </value>
</item>
</dictionary>
</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 @@
<string>my_ssl_key</string>
<string>my_ssl_certificate</string>
<string>my_description</string>
<string>my_sla_xml</string>
</list>
</value>
</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
source=instance_setup_sale_packing_list.getSource(),\n
source_section=instance_setup_sale_packing_list.getSourceSection(),\n
price_currency=instance_setup_sale_packing_list.getPriceCurrency(),\n
start_date=DateTime())\n
start_date=DateTime(),\n
activate_kw={\'tag\': tag})\n
\n
instance_hosting_sale_packing_list_line = sale_packing_list.newContent(\n
portal_type=\'Sale Packing List Line\',\n
resource=service_relative_url,\n
quantity=instance_setup_sale_packing_list_line.getQuantity(),\n
aggregate_list=instance_setup_sale_packing_list_line.getAggregateList(),\n
activate_kw={\'tag\': tag}\n
)\n
return sale_packing_list\n
</string> </value>
</item>
<item>
<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>
<key> <string>id</string> </key>
......
......@@ -61,7 +61,7 @@ hosting_subscription_uid = state_change.kwargs[\'hosting_subscription_uid\']\n
shared = state_change.kwargs[\'shared\']\n
software_type = state_change.kwargs["software_type"]\n
tag = state_change.kwargs[\'tag\']\n
filter_kw = state_change.kwargs["filter_kw"]\n
filter_kw = software_instance.getSlaXmlAsDict()\n
\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
......
......@@ -50,12 +50,22 @@
</item>
<item>
<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
getPreferredInstanceCleanupResource()\n
sale_packing_list = context.SoftwareInstance_createSalePackingList(state_change, service_relative_url)\n
sale_packing_list.confirm()\n
</string> </value>
sale_packing_list = context.SoftwareInstance_createSalePackingList(state_change, service_relative_url, tag=tag)\n
sale_packing_list.confirm(activate_kw={\'tag\':tag})\n
]]></string> </value>
</item>
<item>
<key> <string>_params</string> </key>
......
......@@ -61,7 +61,7 @@ requested_partition_reference = kwargs["partition_reference"]\n
shared = kwargs["shared"]\n
software_type = kwargs["software_type"]\n
instance_xml = kwargs["instance_xml"]\n
filter_kw = kwargs["filter_kw"]\n
sla_xml = kwargs["sla_xml"]\n
\n
# Get root software instance\n
predecessor_software_instance = software_instance\n
......@@ -97,6 +97,7 @@ if (request_software_instance is None):\n
title=requested_partition_reference,\n
source_reference=software_type,\n
text_content=instance_xml,\n
sla_xml=sla_xml,\n
activate_kw={\'tag\': tag},\n
**portal.Base_getNewSoftwareInstanceCoordinate()\n
)\n
......@@ -108,13 +109,13 @@ if (request_software_instance is None):\n
hosting_subscription_uid=hosting_subscription_uid,\n
shared=shared,\n
software_type=software_type,\n
tag=tag,\n
filter_kw=filter_kw)\n
tag=tag)\n
else:\n
# Update existing software instance\n
# Sale Packing List interaction has to be requested automatically with an interaction workflow\n
request_software_instance.edit(\n
text_content=instance_xml,\n
sla_xml=sla_xml,\n
activate_kw={\'tag\': tag},\n
)\n
# Update the predecessor category of the original caller\n
......
......@@ -50,7 +50,9 @@
</item>
<item>
<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
getPreferredInstanceHostingResource()\n
need_to_create_packing_list = False\n
......@@ -63,10 +65,18 @@ else:\n
if sale_packing_list_line.getSimulationState() == \'delivered\':\n
need_to_create_packing_list = True\n
\n
portal = context.getPortalObject()\n
if need_to_create_packing_list:\n
sale_packing_list = context.SoftwareInstance_createSalePackingList(state_change, service_relative_url)\n
sale_packing_list.confirm()\n
</string> </value>
tag = "%s_startInProgress" % software_instance.getUid()\n
if (portal.portal_activities.countMessageWithTag(tag) > 0):\n
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>
<key> <string>_params</string> </key>
......
230
\ No newline at end of file
243
\ No newline at end of file
Person | get_certificate
Person | revoke_certificate
Software Instance Module | view
Software Instance | jump_to_software_instance
Software Instance | view
\ No newline at end of file
SoftwareInstance
Person
\ No newline at end of file
......@@ -41,109 +41,46 @@ class TestVifibCredential(testVifibMixin):
result_list.append("vifib_credential")
return result_list
def createCredentialRequest(self,
first_name="Gabriel",
last_name="Monnerat",
reference="gabriel",
password="123",
default_email_text="gabriel@test.com"):
def stepSetCredentialRequestAutomaticApprovalPreferences(self):
self.setSystemPreference()
default_system_preference = self.portal.portal_preferences.restrictedTraverse(self.getDefaultSitePreferenceId())
self.login("ERP5TypeTestCase")
default_system_preference.edit(preferred_credential_request_automatic_approval=True)
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.portal.ERP5Site_registerCredentialRequest(first_name=first_name,
last_name=last_name,
reference=reference,
password=password,
portal_catalog = self.portal.portal_catalog
self.portal.ERP5Site_registerCredentialRequest(first_name="Vifib",
last_name="Test",
reference="vifib_test",
password="vifib",
career_subordination_title="",
default_email_text=default_email_text,
default_email_text="vifib@vifib.com",
default_telephone_text="223344",
default_address_street_address="Test Street",
default_address_city="Campos",
default_address_city="My Street",
default_address_zip_code="28024030")
self.login("ERP5TypeTestCase")
self.stepTic()
def createSystemPreference(self):
""" """
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")
reference="vifib_test")
mail_message = portal_catalog.getResultValue(portal_type="Mail Message",
follow_up=credential_request)
self.logout()
self.portal.ERP5Site_activeLogin(mail_message.getReference())
self.login("ERP5TypeTestCase")
self.stepTic()
person = portal_catalog.getResultValue(reference="gabriel", portal_type="Person")
self.assertEquals(person.getValidationState(), "validated")
def testERP5Site_registerCredentialRequest(self):
""" Test if the script ERP5Site_registerCredentialRequest will create one
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")
person = portal_catalog.getResultValue(reference="vifib_test", portal_type="Person")
assignment_list = person.objectValues(portal_type="Assignment")
assignment = assignment_list[0]
self.assertEquals(assignment.getFunction(), "customer")
self.assertEquals(assignment.getRole(), "client")
27
\ No newline at end of file
28
\ No newline at end of file
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="TradeModelPath" module="Products.ERP5Type.Document.TradeModelPath"/>
<global name="Trade Model Path" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Computer" module="Products.ERP5Type.Document.Computer"/>
<global name="Computer" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ComputerPartition" module="Products.ERP5Type.Document.ComputerPartition"/>
<global name="Computer Partition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Supply" module="Products.ERP5Type.Document.Supply"/>
<global name="Open Sale Order" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="SupplyLine" module="Products.ERP5Type.Document.SupplyLine"/>
<global name="Open Sale Order Line" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Organisation" module="Products.ERP5Type.Document.Organisation"/>
<global name="Organisation" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Organisation" module="Products.ERP5Type.Document.Organisation"/>
<global name="Organisation" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="AccountingTransaction" module="Products.ERP5Type.Document.AccountingTransaction"/>
<global name="Accounting Period" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="GeographicAddress" module="Products.ERP5Type.Document.GeographicAddress"/>
<global name="Address" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Url" module="Products.ERP5Type.Document.Url"/>
<global name="Email" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Telephone" module="Products.ERP5Type.Document.Telephone"/>
<global name="Telephone" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="SubscriptionItemRootSimulationRule" module="Products.ERP5Type.Document.SubscriptionItemRootSimulationRule"/>
<global name="Subscription Item Root Simulation Rule" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="FloatEquivalenceTester" module="Products.ERP5Type.Document.FloatEquivalenceTester"/>
<global name="Float Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="NetConvertedQuantityEquivalenceTester" module="Products.ERP5Type.Document.NetConvertedQuantityEquivalenceTester"/>
<global name="Net Converted Quantity Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CategoryMembershipEquivalenceTester" module="Products.ERP5Type.Document.CategoryMembershipEquivalenceTester"/>
<global name="Category Membership Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DateTimeEquivalenceTester" module="Products.ERP5Type.Document.DateTimeEquivalenceTester"/>
<global name="DateTime Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DateTimeEquivalenceTester" module="Products.ERP5Type.Document.DateTimeEquivalenceTester"/>
<global name="DateTime Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="VariationEquivalenceTester" module="Products.ERP5Type.Document.VariationEquivalenceTester"/>
<global name="Variation Divergence Tester" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PackingList" module="Products.ERP5Type.Document.PackingList"/>
<global name="Purchase Packing List" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DeliveryLine" module="Products.ERP5Type.Document.DeliveryLine"/>
<global name="Purchase Packing List Line" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="TradeCondition" module="Products.ERP5Type.Document.TradeCondition"/>
<global name="Sale Trade Condition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="TradeCondition" module="Products.ERP5Type.Document.TradeCondition"/>
<global name="Sale Trade Condition" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="SoftwareProduct" module="Products.ERP5Type.Document.SoftwareProduct"/>
<global name="Software Product" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......@@ -10,6 +10,7 @@
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
......@@ -44,6 +45,7 @@
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
......@@ -84,7 +86,127 @@
<key> <string>title</string> </key>
<value> <string>test_software_product</string> </value>
</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>
</pickle>
</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>
......@@ -66,13 +66,16 @@ for order_line in order.getMovementList():\n
computer_partition = None\n
\n
# XXX Duplicated from request method...\n
\n
query_kw = {\n
\'software_release_url\': software_release.getUrlString(),\n
\'portal_type\': \'Computer Partition\',\n
# \'relative_url\': \'computer_module/20110126-E2AE/%\',\n
\'free_for_request\': 1,\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
result_count = software_instance.portal_catalog.countResults(**query_kw)[0][0]\n
offset = max(0, result_count-1)\n
......
85
\ No newline at end of file
88
\ No newline at end of file
software_release_module/test_software_release
software_product_module/test_software_product
\ No newline at end of file
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Alarm" module="Products.ERP5Type.Document.Alarm"/>
<global name="Alarm" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -59,7 +59,7 @@
</item>
<item>
<key> <string>type_class</string> </key>
<value> <string>Folder</string> </value>
<value> <string>Products.Vifib.Tool.SlapTool.SlapTool</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -2,7 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="SlapTool" module="Products.Vifib.Tool.SlapTool"/>
<global name="Slap Tool" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
......
......@@ -59,8 +59,9 @@ portal = person.getPortalObject()\n
kwargs = state_change.kwargs\n
software_release_url_string = state_change.kwargs[\'software_release\']\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
sla_xml = kwargs.get("sla_xml") or ""\n
\n
sale_order_portal_type = "Sale Order"\n
sale_order_line_portal_type = "Sale Order Line"\n
......@@ -96,6 +97,7 @@ if (request_software_instance is None):\n
source_reference=software_type,\n
title=software_title,\n
text_content=instance_xml,\n
sla_xml=sla_xml,\n
activate_kw={\'tag\': tag},\n
**portal.Base_getNewSoftwareInstanceCoordinate()\n
)\n
......@@ -168,6 +170,7 @@ else:\n
# Update existing software instance\n
request_software_instance.edit(\n
text_content=instance_xml,\n
sla_xml=sla_xml,\n
activate_kw={\'tag\': tag},\n
)\n
......
372
\ No newline at end of file
378
\ No newline at end of file
......@@ -180,7 +180,8 @@ class CertificateAuthorityTool(BaseTool):
security.declareProtected(Permissions.AccessContentsInformation, 'getNewCertificate')
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._lockCertificateAuthority()
try:
......@@ -215,7 +216,8 @@ class CertificateAuthorityTool(BaseTool):
security.declareProtected(Permissions.AccessContentsInformation, 'revokeCertificate')
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._lockCertificateAuthority()
try:
......@@ -247,4 +249,19 @@ class CertificateAuthorityTool(BaseTool):
finally:
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)
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved.
# Copyright (c) 2010-2011 Nexedi SA and Contributors. All Rights Reserved.
# Łukasz Nowak <luke@nexedi.com>
# Romain Courteaud <romain@nexedi.com>
#
......@@ -73,7 +73,7 @@ def convertToREST(function):
"""
try:
retval = function(self, *args, **kwd)
except ValueError, log:
except (ValueError, AttributeError), log:
LOG('SlapTool', INFO, 'Converting ValueError to NotFound, real error:',
error=True)
raise NotFound(log)
......@@ -81,7 +81,8 @@ def convertToREST(function):
self.REQUEST.response.setStatus(408)
return self.REQUEST.response
except ValidationFailed:
LOG('SlapTool', INFO, 'Converting ValidationFailed to ValidationFailed, real error:',
LOG('SlapTool', INFO, 'Converting ValidationFailed to ValidationFailed,'\
' real error:',
error=True)
raise ValidationFailed
......@@ -123,7 +124,8 @@ class SlapTool(BaseTool):
# Public GET methods
####################################################
security.declareProtected(Permissions.AccessContentsInformation, 'getComputerInformation')
security.declareProtected(Permissions.AccessContentsInformation,
'getComputerInformation')
def getComputerInformation(self, computer_id):
"""Returns marshalled XML of all needed information for computer
......@@ -149,7 +151,8 @@ class SlapTool(BaseTool):
self._convertToSlapPartition(slave_partition_document, computer_id))
return xml_marshaller.xml_marshaller.dumps(slap_computer)
security.declareProtected(Permissions.AccessContentsInformation, 'getComputerPartitionCertificate')
security.declareProtected(Permissions.AccessContentsInformation,
'getComputerPartitionCertificate')
def getComputerPartitionCertificate(self, computer_id, computer_partition_id):
"""Method to fetch certificate"""
self.REQUEST.response.setHeader('Content-Type', 'text/xml')
......@@ -165,7 +168,8 @@ class SlapTool(BaseTool):
# Public POST methods
####################################################
security.declareProtected(Permissions.AccessContentsInformation, 'setComputerPartitionConnectionXml')
security.declareProtected(Permissions.AccessContentsInformation,
'setComputerPartitionConnectionXml')
def setComputerPartitionConnectionXml(self, computer_id,
computer_partition_id,
connection_xml):
......@@ -176,42 +180,48 @@ class SlapTool(BaseTool):
computer_partition_id,
connection_xml)
security.declareProtected(Permissions.AccessContentsInformation, 'buildingSoftwareRelease')
security.declareProtected(Permissions.AccessContentsInformation,
'buildingSoftwareRelease')
def buildingSoftwareRelease(self, url, computer_id):
"""
Reports that Software Release is being build
"""
return self._buildingSoftwareRelease(url, computer_id)
security.declareProtected(Permissions.AccessContentsInformation, 'availableSoftwareRelease')
security.declareProtected(Permissions.AccessContentsInformation,
'availableSoftwareRelease')
def availableSoftwareRelease(self, url, computer_id):
"""
Reports that Software Release is available
"""
return self._availableSoftwareRelease(url, computer_id)
security.declareProtected(Permissions.AccessContentsInformation, 'softwareReleaseError')
security.declareProtected(Permissions.AccessContentsInformation,
'softwareReleaseError')
def softwareReleaseError(self, url, computer_id, error_log):
"""
Add an error for a software Release workflow
"""
return self._softwareReleaseError(url, computer_id, error_log)
security.declareProtected(Permissions.AccessContentsInformation, 'buildingComputerPartition')
security.declareProtected(Permissions.AccessContentsInformation,
'buildingComputerPartition')
def buildingComputerPartition(self, computer_id, computer_partition_id):
"""
Reports that Computer Partition is being build
"""
return self._buildingComputerPartition(computer_id, computer_partition_id)
security.declareProtected(Permissions.AccessContentsInformation, 'availableComputerPartition')
security.declareProtected(Permissions.AccessContentsInformation,
'availableComputerPartition')
def availableComputerPartition(self, computer_id, computer_partition_id):
"""
Reports that Computer Partition is available
"""
return self._availableComputerPartition(computer_id, computer_partition_id)
security.declareProtected(Permissions.AccessContentsInformation, 'softwareInstanceError')
security.declareProtected(Permissions.AccessContentsInformation,
'softwareInstanceError')
def softwareInstanceError(self, computer_id,
computer_partition_id, error_log):
"""
......@@ -220,31 +230,36 @@ class SlapTool(BaseTool):
return self._softwareInstanceError(computer_id, computer_partition_id,
error_log)
security.declareProtected(Permissions.AccessContentsInformation, 'startedComputerPartition')
security.declareProtected(Permissions.AccessContentsInformation,
'startedComputerPartition')
def startedComputerPartition(self, computer_id, computer_partition_id):
"""
Reports that Computer Partition is started
"""
return self._startedComputerPartition(computer_id, computer_partition_id)
security.declareProtected(Permissions.AccessContentsInformation, 'stoppedComputerPartition')
security.declareProtected(Permissions.AccessContentsInformation,
'stoppedComputerPartition')
def stoppedComputerPartition(self, computer_id, computer_partition_id):
"""
Reports that Computer Partition is stopped
"""
return self._stoppedComputerPartition(computer_id, computer_partition_id)
security.declareProtected(Permissions.AccessContentsInformation, 'destroyedComputerPartition')
security.declareProtected(Permissions.AccessContentsInformation,
'destroyedComputerPartition')
def destroyedComputerPartition(self, computer_id, computer_partition_id):
"""
Reports that Computer Partition is destroyed
"""
return self._destroyedComputerPartition(computer_id, computer_partition_id)
security.declareProtected(Permissions.AccessContentsInformation, 'requestComputerPartition')
def requestComputerPartition(self, computer_id, computer_partition_id,
software_release, software_type, partition_reference,
shared_xml, partition_parameter_xml, filter_xml):
security.declareProtected(Permissions.AccessContentsInformation,
'requestComputerPartition')
def requestComputerPartition(self, computer_id=None,
computer_partition_id=None, software_release=None, software_type=None,
partition_reference=None, shared_xml=None, partition_parameter_xml=None,
filter_xml=None):
"""
Asynchronously requests creation of computer partition for assigned
parameters
......@@ -260,7 +275,8 @@ class SlapTool(BaseTool):
software_release, software_type, partition_reference,
shared_xml, partition_parameter_xml, filter_xml)
security.declareProtected(Permissions.AccessContentsInformation, 'useComputer')
security.declareProtected(Permissions.AccessContentsInformation,
'useComputer')
def useComputer(self, computer_id, use_string):
"""Entry point to reporting usage of a computer."""
#computer_document = self._getComputerDocument(computer_id)
......@@ -283,7 +299,8 @@ class SlapTool(BaseTool):
return 'Content properly posted.'
security.declareProtected(Permissions.AccessContentsInformation, 'loadComputerConfigurationFromXML')
security.declareProtected(Permissions.AccessContentsInformation,
'loadComputerConfigurationFromXML')
def loadComputerConfigurationFromXML(self, xml):
"Load the given xml as configuration for the computer object"
computer_dict = xml_marshaller.xml_marshaller.loads(xml)
......@@ -291,8 +308,10 @@ class SlapTool(BaseTool):
computer.Computer_updateFromDict(computer_dict)
return 'Content properly posted.'
security.declareProtected(Permissions.AccessContentsInformation, 'useComputerPartition')
def useComputerPartition(self, computer_id, computer_partition_id, use_string):
security.declareProtected(Permissions.AccessContentsInformation,
'useComputerPartition')
def useComputerPartition(self, computer_id, computer_partition_id,
use_string):
"""Warning : deprecated method."""
computer_document = self._getComputerDocument(computer_id)
computer_partition_document = self._getComputerPartitionDocument(
......@@ -303,7 +322,8 @@ class SlapTool(BaseTool):
return """Content properly posted.
WARNING : this method is deprecated. Please use useComputer."""
security.declareProtected(Permissions.AccessContentsInformation, 'registerComputerPartition')
security.declareProtected(Permissions.AccessContentsInformation,
'registerComputerPartition')
def registerComputerPartition(self, computer_reference,
computer_partition_reference):
"""
......@@ -326,8 +346,7 @@ class SlapTool(BaseTool):
result_dict = {}
if xml is not None and xml != '':
tree = etree.fromstring(xml.encode('utf-8'))
for element in tree.iter(tag=etree.Element):
if element.tag == 'parameter':
for element in tree.findall('parameter'):
key = element.get('id')
value = result_dict.get(key, None)
if value is not None:
......@@ -414,7 +433,8 @@ class SlapTool(BaseTool):
elif movement.getResource() == \
portal_preferences.getPreferredInstanceCleanupResource():
if movement.getSimulationState() in ('confirmed', 'started', 'stopped'):
if movement.getSimulationState() in ('confirmed', 'started',
'stopped'):
slap_partition._need_modification = 1
else:
......@@ -440,7 +460,8 @@ class SlapTool(BaseTool):
Reports that Software Release is being build
"""
computer_document = self._getComputerDocument(computer_id)
computer_document.startSoftwareReleaseInstallation(software_release_url=url)
computer_document.startSoftwareReleaseInstallation(
software_release_url=url)
@convertToREST
def _availableSoftwareRelease(self, url, computer_id):
......@@ -552,7 +573,8 @@ class SlapTool(BaseTool):
Returns XML representation of partition with HTTP code 200 OK
In case if this request is still being processed data contain
"Computer Partition is being processed" and HTTP code is 408 Request Timeout
"Computer Partition is being processed" and HTTP code is 408 Request
Timeout
In any other case returns not important data and HTTP code is 403 Forbidden
"""
......@@ -579,8 +601,19 @@ class SlapTool(BaseTool):
instance_xml = etree.tostring(instance, pretty_print=True,
xml_declaration=True, encoding='utf-8')
software_instance_document = self._getSoftwareInstanceForComputerPartition(
computer_id,
instance = etree.Element('instance')
for parameter_id, parameter_value in filter_kw.iteritems():
# cast everything to string
parameter_value = str(parameter_value)
etree.SubElement(instance, "parameter",
attrib={'id':parameter_id}).text = parameter_value
sla_xml = etree.tostring(instance, pretty_print=True,
xml_declaration=True, encoding='utf-8')
if computer_id and computer_partition_id:
# requested by Software Instance, there is already top part of tree
software_instance_document = self.\
_getSoftwareInstanceForComputerPartition(computer_id,
computer_partition_id)
software_instance_document.requestSoftwareInstance(
software_release=software_release,
......@@ -588,7 +621,7 @@ class SlapTool(BaseTool):
partition_reference=partition_reference,
shared=shared,
instance_xml=instance_xml,
filter_kw=filter_kw)
sla_xml=sla_xml)
# Get requested software instance
requested_software_instance = software_instance_document.portal_catalog.\
......@@ -601,12 +634,33 @@ class SlapTool(BaseTool):
predecessor_related_uid=software_instance_document.getUid(),
title=partition_reference,
)
else:
# requested as root, so done by human
person = self.getPortalObject()\
.ERP5Site_getAuthenticatedMemberPersonValue()
person.requestSoftwareInstance(software_release=software_release,
software_type=software_type,
software_title=partition_reference,
shared=shared,
instance_xml=instance_xml,
sla_xml=sla_xml)
requested_software_instance = person.portal_catalog.\
getResultValue(
portal_type="Software Instance",
# In order be in sync with defaults of person.
# requestSoftwareInstance it is required to default here
# too
source_reference=software_type or 'RootSoftwareInstance',
title=partition_reference,
)
if requested_software_instance is None:
raise SoftwareInstanceNotReady
else:
movement = self._getSalePackingListLineForComputerPartition(
requested_software_instance)
if movement is None:
raise SoftwareInstanceNotReady
software_instance = SoftwareInstance(
**self._getSalePackingListLineAsSoftwareInstance(
movement))
......@@ -676,8 +730,8 @@ class SlapTool(BaseTool):
software_instance = packing_list_line.getAggregateValue(
portal_type="Software Instance")
if software_instance is None:
raise NotFound, "No software instance found for: %s - %s" % (computer_id,
computer_partition_id)
raise NotFound, "No software instance found for: %s - %s" % (
computer_id, computer_partition_id)
else:
return software_instance
......@@ -773,7 +827,8 @@ class SlapTool(BaseTool):
usage_report_sale_packing_list_document.start()
# Adds a new SPL line for each Computer Partition
for computer_partition_usage in unmarshalled_usage.computer_partition_usage_list:
for computer_partition_usage in unmarshalled_usage\
.computer_partition_usage_list:
#Get good packing list line for a computer_partition
computer_partition_document = self.\
_getComputerPartitionDocument(
......
......@@ -47,6 +47,7 @@ from Products.ERP5Security.ERP5GroupManager import ConsistencyError, NO_CACHE_MO
from Products.ERP5Type.ERP5Type \
import ERP5TYPE_SECURITY_GROUP_ID_GENERATION_SCRIPT
from Products.ERP5Type.Cache import CachingMethod
from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery
#Form for new plugin in ZMI
manage_addVifibMachineAuthenticationPluginForm = PageTemplateFile(
......@@ -70,11 +71,14 @@ def addVifibMachineAuthenticationPlugin(dispatcher, id, title=None, REQUEST=None
def getUserByLogin(portal, login):
if isinstance(login, basestring):
login = login,
result = portal.portal_catalog.unrestrictedSearchResults(
select_expression='reference',
portal_type=["Computer", "Software Instance"],
machine_query = Query(portal_type=["Computer", "Software Instance"],
validation_state="validated",
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
# parameters to unrestrictedSearchResults to restrict result set.
# This is done because the following values can match person with
......@@ -92,7 +96,6 @@ def getUserByLogin(portal, login):
# by default (feature).
return [x.getObject() for x in result if x['reference'] in login]
class VifibMachineAuthenticationPlugin(BasePlugin):
"""
Plugin to authenicate as machines.
......
......@@ -86,6 +86,7 @@ class TestVifibSlapWebService(testVifibMixin):
purchase_packing_list_line_portal_type = "Purchase Packing List Line"
purchase_packing_list_portal_type = "Purchase Packing List"
sale_packing_list_line_portal_type = "Sale Packing List Line"
sale_order_line_portal_type = "Sale Order Line"
sale_packing_list_portal_type = "Sale Packing List"
service_portal_type = "Service"
slave_partition_portal_type = "Slave Partition"
......@@ -122,7 +123,7 @@ class TestVifibSlapWebService(testVifibMixin):
self.assertEqual(got, {})
########################################
# Ĥelpers
# Helpers
########################################
def _softwareInstance_getComputerPartition(self, software_instance):
sale_packing_list_line = software_instance\
......@@ -367,10 +368,18 @@ class TestVifibSlapWebService(testVifibMixin):
self.portal.portal_catalog.getResultValue(
uid=sequence['software_instance_uid']).requestDestroyComputerPartition()
def stepRequestSoftwareInstanceDestroyRaisesValueError(self, sequence, **kw):
self.assertRaises(ValueError, self.portal.portal_catalog.getResultValue(
uid=sequence['software_instance_uid']).requestDestroyComputerPartition)
def stepRequestSoftwareInstanceStart(self, sequence, **kw):
self.portal.portal_catalog.getResultValue(
uid=sequence['software_instance_uid']).requestStartComputerPartition()
def stepRequestSoftwareInstanceStartRaisesValueError(self, sequence, **kw):
self.assertRaises(ValueError, self.portal.portal_catalog.getResultValue(
uid=sequence['software_instance_uid']).requestStartComputerPartition)
def stepRequestSoftwareInstanceStop(self, sequence, **kw):
self.portal.portal_catalog.getResultValue(
uid=sequence['software_instance_uid']).requestStopComputerPartition()
......@@ -561,6 +570,10 @@ class TestVifibSlapWebService(testVifibMixin):
global REMOTE_USER
REMOTE_USER = sequence['software_instance_reference']
def stepSlapLoginTestVifibCustomer(self, sequence, **kw):
global REMOTE_USER
REMOTE_USER = 'test_vifib_customer'
########################################
# Typical sequences for scenarios
########################################
......@@ -1470,6 +1483,56 @@ class TestVifibSlapWebService(testVifibMixin):
partition_reference=requested_reference,
partition_parameter_kw=requested_parameter_dict)
def stepRequestSoftwareInstanceStartCheckSerializeIsCalled(self, sequence):
# check that on being_requested serialise is being called
# code stolen from testERP5Security:test_MultiplePersonReferenceConcurrentTransaction
class DummyTestException(Exception):
pass
def verify_serialize_call(self):
# it is checking that anything below computer_module raises exception
# thanks to this this test do not have to be destructive
if self.getPortalType() == "Software Instance":
raise DummyTestException
else:
return self.serialize_call()
from Products.ERP5Type.Base import Base
Base.serialize_call = Base.serialize
Base.serialize = verify_serialize_call
try:
self.assertRaises(DummyTestException,
self.portal.portal_catalog.getResultValue(
uid=sequence['software_instance_uid']).requestStartComputerPartition)
finally:
Base.serialize = Base.serialize_call
def stepRequestSoftwareInstanceDestroyCheckSerializeIsCalled(self, sequence):
# check that on being_requested serialise is being called
# code stolen from testERP5Security:test_MultiplePersonReferenceConcurrentTransaction
class DummyTestException(Exception):
pass
def verify_serialize_call(self):
# it is checking that anything below computer_module raises exception
# thanks to this this test do not have to be destructive
if self.getPortalType() == "Software Instance":
raise DummyTestException
else:
return self.serialize_call()
from Products.ERP5Type.Base import Base
Base.serialize_call = Base.serialize
Base.serialize = verify_serialize_call
try:
self.assertRaises(DummyTestException,
self.portal.portal_catalog.getResultValue(
uid=sequence['software_instance_uid']).requestDestroyComputerPartition)
finally:
Base.serialize = Base.serialize_call
def stepRequestComputerComputerPartitionCheckSerializeCalledOnSelected(
self, sequence, **kw):
software_release_uri = sequence['software_release_uri']
......@@ -1504,7 +1567,8 @@ class TestVifibSlapWebService(testVifibMixin):
software_type=requested_reference,
shared=False,
filter_kw={},
instance_xml=self.minimal_correct_xml)
instance_xml=self.minimal_correct_xml,
sla_xml=self.minimal_correct_xml)
finally:
Base.serialize = Base.serialize_call
......@@ -2951,6 +3015,51 @@ class TestVifibSlapWebService(testVifibMixin):
portal_type=self.sale_packing_list_line_portal_type)
self.assertEqual(1, len(computer_partition_sale_packing_list_line_list))
def stepCheckPersonRequestedSoftwareInstanceAndRelatedComputerPartition(self,
sequence, **kw):
software_instance = self.portal.portal_catalog.getResultValue(
uid=sequence['software_instance_uid'])
# in this test it is required to assume that requested_reference
computer_partition = self._softwareInstance_getComputerPartition(
software_instance)
# There should be only one Sale Packing List Line
sale_packing_list_line_list = software_instance\
.getAggregateRelatedValueList(
portal_type=self.sale_packing_list_line_portal_type)
self.assertEqual(1, len(sale_packing_list_line_list))
sale_packing_list_line = sale_packing_list_line_list[0]
# This Sale Packing List Line shall have only one Computer Partition
computer_partition_list = sale_packing_list_line.getAggregateValueList(
portal_type='Computer Partition')
self.assertEqual(1, len(computer_partition_list))
computer_partition = computer_partition_list[0]
# This Computer Partition shall have only Sale Packing List Line related
computer_partition_sale_packing_list_line_list = computer_partition\
.getAggregateRelatedValueList(
portal_type=self.sale_packing_list_line_portal_type)
self.assertEqual(1, len(computer_partition_sale_packing_list_line_list))
# There should be only one Sale Order Line
sale_order_line_list = software_instance\
.getAggregateRelatedValueList(
portal_type=self.sale_order_line_portal_type)
self.assertEqual(1, len(sale_order_line_list))
sale_order_line = sale_order_line_list[0]
# This Sale Order Line shall have only one Computer Partition
computer_partition_list = sale_order_line.getAggregateValueList(
portal_type='Computer Partition')
self.assertEqual(1, len(computer_partition_list))
computer_partition = computer_partition_list[0]
# This Computer Partition shall have only Sale Order Line related
computer_partition_sale_order_line_list = computer_partition\
.getAggregateRelatedValueList(
portal_type=self.sale_order_line_portal_type)
self.assertEqual(1, len(computer_partition_sale_order_line_list))
def stepCheckSoftwareInstanceAndRelatedComputerPartition(self,
sequence, **kw):
software_instance_uid = sequence['software_instance_uid']
......@@ -4007,12 +4116,6 @@ class TestVifibSlapWebService(testVifibMixin):
sequence['requested_filter_dict'] = dict(
computer_guid=sequence['computer_reference'])
def test_ComputerPartition_request_filter_computer_guid(self):
"""
Check that requesting with filter computer_guid key works as expected
"""
self.computer_partition_amount = 2
sequence_list = SequenceList()
prepare_another_computer_sequence_string = """
StoreComputerReference
LoginTestVifibAdmin
......@@ -4023,7 +4126,7 @@ class TestVifibSlapWebService(testVifibMixin):
SlapLoginCurrentComputer
FormatComputer
Tic
SlapLogout""" + self.prepare_software_release_confirmed_packing_list + """
SlapLogout""" + prepare_software_release_confirmed_packing_list + """
LoginTestVifibAdmin
RequestSoftwareInstallation
......@@ -4038,12 +4141,19 @@ class TestVifibSlapWebService(testVifibMixin):
SetRequestedFilterParameterDict
RestoreComputerReference
"""
def test_ComputerPartition_request_filter_computer_guid(self):
"""
Check that requesting with filter computer_guid key works as expected
"""
self.computer_partition_amount = 2
sequence_list = SequenceList()
# There are two partitions on another computer
# so request shall be processed twice correctly, 3rd time it shall
# fail
sequence_string = \
self.prepare_install_requested_computer_partition_sequence_string + \
prepare_another_computer_sequence_string + '\
self.prepare_another_computer_sequence_string + '\
SlapLoginCurrentSoftwareInstance \
RequestComputerPartitionNotReadyResponse \
Tic \
......@@ -6883,6 +6993,293 @@ class TestVifibSlapWebService(testVifibMixin):
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
########################################
# Person using PKI/Slap interface
########################################
def _safe_revoke_certificate(self, person):
from AccessControl import getSecurityManager
user = getSecurityManager().getUser().getId()
try:
self.login('ERP5TypeTestCase')
person.revokeCertificate()
except ValueError, err:
if 'No certificate for' in err.message:
pass
else:
raise
finally:
self.login(user)
def test_person_request_new_certificate(self):
"""Checks that Person is capable to ask for new certificate"""
self.login()
self.portal.portal_certificate_authority._checkCertificateAuthority()
person = self.portal.ERP5Site_getAuthenticatedMemberPersonValue(
'test_vifib_user_admin')
self._safe_revoke_certificate(person)
self.login('test_vifib_user_admin')
certificate = person.getCertificate()
self.assertTrue('CN=test_vifib_user_admin' in certificate['certificate'])
def test_person_request_revoke_certificate(self):
"""Chekcs that Person is capable to ask for revocation of certificate"""
self.login()
self.portal.portal_certificate_authority._checkCertificateAuthority()
person = self.portal.ERP5Site_getAuthenticatedMemberPersonValue(
'test_vifib_user_admin')
self._safe_revoke_certificate(person)
self.login('test_vifib_user_admin')
certificate = person.getCertificate()
self.assertTrue('CN=test_vifib_user_admin' in certificate['certificate'])
person.revokeCertificate()
def test_person_request_new_certificate_twice(self):
"""Checks that if Person asks twice for a certificate the next call
fails"""
self.login()
self.portal.portal_certificate_authority._checkCertificateAuthority()
person = self.portal.ERP5Site_getAuthenticatedMemberPersonValue(
'test_vifib_user_admin')
self._safe_revoke_certificate(person)
self.login('test_vifib_user_admin')
certificate = person.getCertificate()
self.assertTrue('CN=test_vifib_user_admin' in certificate['certificate'])
self.assertRaises(ValueError, person.getCertificate)
def test_person_request_certificate_for_another_person(self):
"""Checks that if Person tries to request ceritifcate for someone else it
will fail"""
from AccessControl import Unauthorized
self.login()
self.portal.portal_certificate_authority._checkCertificateAuthority()
person = self.portal.ERP5Site_getAuthenticatedMemberPersonValue(
'test_vifib_user_admin')
self._safe_revoke_certificate(person)
self.login('test_hr_admin')
self.assertRaises(Unauthorized, person.getCertificate)
def test_person_request_revoke_certificate_for_another_person(self):
"""Checks that if Person tries to request ceritifcate for someone else it
will fail"""
from AccessControl import Unauthorized
self.login()
self.portal.portal_certificate_authority._checkCertificateAuthority()
person = self.portal.ERP5Site_getAuthenticatedMemberPersonValue(
'test_vifib_user_admin')
self._safe_revoke_certificate(person)
self.login('test_vifib_user_admin')
certificate = person.getCertificate()
self.assertTrue('CN=test_vifib_user_admin' in certificate['certificate'])
self.login('test_hr_admin')
self.assertRaises(Unauthorized, person.revokeCertificate)
def stepPersonRequestSlapSoftwareInstanceNotFoundResponse(self, sequence,
**kw):
software_release = sequence['software_release_uri']
self.slap = slap.slap()
self.slap.initializeConnection(self.server_url)
open_order = self.slap.registerOpenOrder()
self.assertRaises(slap.NotFoundError, open_order.request,
software_release=software_release,
software_type=sequence.get('software_type', 'software_type'),
partition_reference=sequence.get('requested_reference',
'requested_reference'),
partition_parameter_kw=sequence.get('requested_parameter_dict', {}),
filter_kw=sequence.get('requested_filter_dict', {})
)
def stepPersonRequestSlapSoftwareInstanceNotReadyResponse(self, sequence,
**kw):
software_release = sequence['software_release_uri']
self.slap = slap.slap()
self.slap.initializeConnection(self.server_url)
open_order = self.slap.registerOpenOrder()
self.assertRaises(slap.ResourceNotReady, open_order.request,
software_release=software_release,
software_type=sequence.get('software_type', 'software_type'),
partition_reference=sequence.get('requested_reference',
'requested_reference'),
partition_parameter_kw=sequence.get('requested_parameter_dict', {}),
filter_kw=sequence.get('requested_filter_dict', {})
)
def stepSetRandomRequestedReference(self, sequence, **kw):
sequence['requested_reference'] = self.id() + str(random())
def stepSetCurrentPersonSlapRequestedSoftwareInstance(self, sequence, **kw):
software_instance_list = self.portal.portal_catalog(
portal_type=self.software_instance_portal_type,
title=sequence['requested_reference'])
self.assertEqual(1, len(software_instance_list))
software_instance = software_instance_list[0]
sequence.edit(
software_instance_uid=software_instance.getUid(),
software_instance_reference=software_instance.getReference(),
hosting_subscription_uid=software_instance.getAggregateRelatedValue(
portal_type='Sale Order Line').getAggregateValue(
portal_type='Hosting Subscription').getUid())
def stepPersonRequestSlapSoftwareInstance(self, sequence, **kw):
software_release = sequence['software_release_uri']
self.slap = slap.slap()
self.slap.initializeConnection(self.server_url)
open_order = self.slap.registerOpenOrder()
requested_slap_computer_partition = open_order.request(
software_release=software_release,
software_type=sequence.get('software_type', 'software_type'),
partition_reference=sequence['requested_reference'],
partition_parameter_kw=sequence.get('requested_parameter_dict', {}),
filter_kw=sequence.get('requested_filter_dict', {}))
sequence.edit(
requested_slap_computer_partition=requested_slap_computer_partition,
requested_computer_partition_reference=\
requested_slap_computer_partition.getId())
def test_person_request_ComputerPartition(self):
"""Checks that Person using Slap interface is able to request Computer
Partition"""
self.computer_partition_amount = 1
sequence_list = SequenceList()
sequence_string = self.prepare_published_software_release + \
self.prepare_formated_computer + """
LoginTestVifibAdmin
RequestSoftwareInstallation
Tic
Logout
SlapLoginCurrentComputer
ComputerSoftwareReleaseAvailable
Tic
SlapLogout
SetRandomRequestedReference
SlapLoginTestVifibCustomer
PersonRequestSlapSoftwareInstanceNotReadyResponse
Tic
SlapLogout
SlapLoginTestVifibCustomer
PersonRequestSlapSoftwareInstanceNotReadyResponse
Tic
SlapLogout
LoginDefaultUser
ConfirmOrderedSaleOrderActiveSense
Tic
Logout
SlapLoginTestVifibCustomer
PersonRequestSlapSoftwareInstance
Tic
SlapLogout
LoginDefaultUser
SetCurrentPersonSlapRequestedSoftwareInstance
CheckPersonRequestedSoftwareInstanceAndRelatedComputerPartition
Logout
SlapLoginCurrentSoftwareInstance
CheckRequestedComputerPartitionCleanParameterList
SlapLogout
LoginTestVifibCustomer
CheckViewCurrentSoftwareInstance
CheckWriteCurrentSoftwareInstance
Tic
Logout
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
def stepSoftwareInstanceSaleOrderConfirmRaisesValueError(self, sequence,
**kw):
"""Checks that current software instance is realted only with sale order
and that this sale order cannot be confirmed
In Vifib implementation sale order which cannot find free computer partition
raises ValueError"""
software_instance = self.portal.portal_catalog.getResultValue(
uid=sequence['software_instance_uid'])
aggregate_value_list = software_instance.getAggregateRelatedValueList(portal_type=[self.sale_packing_list_line_portal_type, self.sale_order_line_portal_type])
self.assertEqual(1, len(aggregate_value_list))
self.assertTrue(self.sale_order_line_portal_type in [q.getPortalType() for\
q in aggregate_value_list])
sale_order_line = aggregate_value_list[0]
sale_order = sale_order_line.getParentValue()
self.assertRaises(ValueError, sale_order.confirm)
def test_person_request_ComputerPartition_filter_computer_guid(self):
"""Check that requesting with computer_guid in filter_kw works as
expected in case of person request"""
self.computer_partition_amount = 1
sequence_list = SequenceList()
# There is only one partition on each computer, which has installed
# software release. But as request has sla parameter, the partition
# on another computer is not selected, as not following SLA.
sequence_string = self.prepare_published_software_release + \
self.prepare_formated_computer + """
LoginTestVifibAdmin
RequestSoftwareInstallation
Tic
Logout
SlapLoginCurrentComputer
ComputerSoftwareReleaseAvailable
Tic
SlapLogout
""" + \
self.prepare_another_computer_sequence_string + """
LoginTestVifibAdmin
RequestSoftwareInstallation
Tic
Logout
SetRandomRequestedReference
SlapLoginTestVifibCustomer
PersonRequestSlapSoftwareInstanceNotReadyResponse
Tic
SlapLogout
SlapLoginTestVifibCustomer
PersonRequestSlapSoftwareInstanceNotReadyResponse
Tic
SlapLogout
LoginDefaultUser
ConfirmOrderedSaleOrderActiveSense
Tic
Logout
SlapLoginTestVifibCustomer
PersonRequestSlapSoftwareInstance
Tic
SlapLogout
LoginDefaultUser
SetCurrentPersonSlapRequestedSoftwareInstance
CheckPersonRequestedSoftwareInstanceAndRelatedComputerPartition
Logout
SelectYetAnotherRequestedReference
SlapLoginTestVifibCustomer
PersonRequestSlapSoftwareInstanceNotReadyResponse
Tic
SlapLogout
LoginDefaultUser
SetCurrentPersonSlapRequestedSoftwareInstance
SoftwareInstanceSaleOrderConfirmRaisesValueError
Logout
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
########################################
# Bug related tests
########################################
......@@ -6913,6 +7310,59 @@ class TestVifibSlapWebService(testVifibMixin):
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
def test_bug_doubleClickOnStart(self):
sequence_list = SequenceList()
sequence_string = self\
.prepare_stopped_computer_partition_sequence_string + """
LoginTestVifibCustomer
RequestSoftwareInstanceStart
RequestSoftwareInstanceStartRaisesValueError
Tic
Logout
LoginDefaultUser
CheckComputerPartitionInstanceHostingSalePackingListConfirmed
Logout
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
def test_bug_doubleClickOnStart_serializeIsCalled(self):
sequence_list = SequenceList()
sequence_string = self\
.prepare_stopped_computer_partition_sequence_string + """
LoginTestVifibCustomer
RequestSoftwareInstanceStartCheckSerializeIsCalled
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
def test_bug_doubleClickOnDestroy(self):
sequence_list = SequenceList()
sequence_string = self\
.prepare_installed_computer_partition_sequence_string + """
LoginTestVifibCustomer
RequestSoftwareInstanceDestroy
RequestSoftwareInstanceDestroyRaisesValueError
Tic
Logout
LoginDefaultUser
CheckComputerPartitionInstanceCleanupSalePackingListConfirmed
Logout
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
def test_bug_doubleClickOnDestroy_serializeIsCalled(self):
sequence_list = SequenceList()
sequence_string = self\
.prepare_installed_computer_partition_sequence_string + """
LoginTestVifibCustomer
RequestSoftwareInstanceDestroyCheckSerializeIsCalled
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
# class IComputerPartition
# def started():
......
......@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
import glob
import os
version = '0.3-dev'
version = '0.4-dev'
name = 'slapos.core'
long_description = open("README.txt").read() + "\n" + \
open("CHANGES.txt").read() + "\n"
......@@ -33,7 +33,7 @@ setup(name=name,
install_requires=[
'Flask', # used by proxy
'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
'setuptools', # namespaces
'supervisor', # slapgrid uses supervisor to manage processes
......
......@@ -18,4 +18,5 @@ ipv4_local_network = 10.0.0.0/16
[slapproxy]
host = 127.0.0.1
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 @@
##############################################################################
from optparse import OptionParser, Option
from xml_marshaller import xml_marshaller
from pwd import getpwnam
import ConfigParser
import grp
import logging
import netaddr
import netifaces
import os
import pwd
import random
import slapos.slap as slap
import socket
......@@ -41,6 +41,34 @@ import subprocess
import sys
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):
"""
......@@ -195,6 +223,8 @@ class Computer:
slap_instance.initializeConnection(config.master_url,
**connection_dict)
slap_computer = slap_instance.registerComputer(self.reference)
if config.dry_run:
return
return slap_computer.updateConfiguration(
xml_marshaller.dumps(_getDict(self)))
......@@ -280,7 +310,7 @@ class Computer:
slapsoft.path = self.software_root
if alter_user:
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.chmod(self.software_root, 0755)
......@@ -365,7 +395,7 @@ class Partition:
if not os.path.exists(self.path):
os.mkdir(self.path, 0750)
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.chmod(self.path, 0750)
......@@ -402,12 +432,12 @@ class User:
except KeyError:
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:
user_parameter_list.extend(['-G', ','.join(self.additional_group_list)])
user_parameter_list.append(self.name)
try:
pwd.getpwnam(self.name)
getpwnam(self.name)
except KeyError:
callAndRead(['useradd'] + user_parameter_list)
else:
......@@ -425,7 +455,7 @@ class User:
"""
try:
pwd.getpwnam(self.name)
getpwnam(self.name)
return True
except KeyError:
......@@ -463,7 +493,7 @@ class Tap:
owner_id = int(open(check_file).read().strip())
except Exception:
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(['ip', 'link', 'set', self.name, 'up'])
......@@ -707,6 +737,10 @@ class Parser(OptionParser):
help="Shall slapformat alter user database [default: True]"),
Option('--alter_network', choices=['True', 'False'],
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):
......@@ -831,6 +865,7 @@ def run(config):
alter_network=config.alter_network)
# Dumping and sending to the erp5 the current configuration
if not config.dry_run:
computer.dump(config.computer_xml)
config.logger.info('Posting information to %r' % config.master_url)
computer.send(config)
......@@ -904,11 +939,17 @@ class Config:
self.logger.error(message)
raise UsageError(message)
if not self.dry_run:
if self.alter_user:
self.checkRequiredBinary(['groupadd', 'useradd', 'usermod'])
if self.alter_network:
self.checkRequiredBinary(['brctl', 'ip', 'tunctl'])
self.checkRequiredBinary(['ip', 'tunctl'])
# Required, even for dry run
if self.alter_network:
self.checkRequiredBinary(['brctl'])
if self.dry_run:
root_needed = False
# check root
if root_needed and os.getuid() != 0:
......@@ -937,6 +978,8 @@ class Config:
if self.verbose:
self.logger.setLevel(logging.DEBUG)
self.logger.debug("Verbose mode enabled.")
if self.dry_run:
self.logger.info("Dry-run mode enabled.")
# Calculate path once
self.computer_xml = os.path.abspath(self.computer_xml)
......@@ -944,6 +987,10 @@ class Config:
def main():
"Run default configuration."
global os
global callAndRead
global getpwnam
real_callAndRead = callAndRead
usage = "usage: %s [options] CONFIGURATION_FILE" % sys.argv[0]
try:
......@@ -951,6 +998,33 @@ def main():
options, configuration_file_path = Parser(usage=usage).check_args()
config = Config()
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)
except UsageError, err:
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