Commit 3e5c2ea7 authored by Gabriel Monnerat's avatar Gabriel Monnerat

merged with master

parent 36524879
0.4 (unreleased)
0.9 (not yet released)
================
* slapformat: Fix issue of bridge not connected with real interface on
Linux >= 2.6.39 [Arnaud Fontaine]
* slapconsole: Simplify usage and use configuration file. You can now
just run slapconsole and type things like "request(kvm, 'mykvm')".
[Cedric de Saint Martin]
0.8 (2011-06-27)
================
* slapgrid: Bugfix for temporary extends cache permissions. [Łukasz Nowak]
0.7 (2011-06-27)
================
* slapgrid: Fallback to buildout in own search path. [Łukasz Nowak]
0.6 (2011-06-27)
================
* slap: Fix bug: state shall be XML encapsulated. [Łukasz Nowak]
0.5 (2011-06-24)
================
* slapgrid: Use temporary extends-cache directory in order to make faster
remote profile refresh. [Łukasz Nowak]
0.4 (2011-06-24)
================
* general: Polish requirement versions. [Arnaud Fontaine]
......
......@@ -9,6 +9,11 @@ find-links =
versions = versions
# Separate development profile from system python packages
include-site-packages = false
exec-sitecustomize = false
allowed-eggs-from-site-packages =
[pyflakes]
recipe = zc.recipe.egg
scripts =
......@@ -20,6 +25,7 @@ eggs =
[slapos]
recipe = z3c.recipe.scripts
eggs =
slapos.libnetworkcache
zc.buildout
slapos.core
ipython
......@@ -30,4 +36,4 @@ eggs =
interpreter = python
[versions]
zc.buildout = 1.5.3-dev-SlapOS-001
zc.buildout = 1.5.3-dev-SlapOS-004
erp5_software_pdm
erp5_computer_immobilisation
\ No newline at end of file
erp5_computer_immobilisation
erp5_software_pdm
\ No newline at end of file
......@@ -13,8 +13,8 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -22,10 +22,7 @@
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -33,10 +30,7 @@
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -47,7 +41,6 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -58,8 +51,8 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......
......@@ -13,8 +13,8 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -22,10 +22,7 @@
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -33,10 +30,7 @@
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -47,7 +41,6 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -58,8 +51,8 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......
......@@ -13,8 +13,8 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -22,10 +22,7 @@
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -33,10 +30,7 @@
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -47,7 +41,6 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -58,8 +51,8 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......
......@@ -13,8 +13,8 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -22,10 +22,7 @@
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -33,10 +30,7 @@
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -47,7 +41,6 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -58,8 +51,8 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......
......@@ -13,8 +13,8 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -22,10 +22,7 @@
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -33,10 +30,7 @@
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -47,7 +41,6 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -58,8 +51,8 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......
......@@ -13,8 +13,8 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -22,10 +22,7 @@
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -33,10 +30,7 @@
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -47,7 +41,6 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -58,8 +51,8 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......
......@@ -24,6 +24,22 @@
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
......@@ -65,6 +81,14 @@
<key> <string>portal_type</string> </key>
<value> <string>System Preference</string> </value>
</item>
<item>
<key> <string>preferred_credential_recovery_automatic_approval</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>preferred_credential_request_automatic_approval</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>preferred_hide_rows_on_no_search_criterion</string> </key>
<value> <int>1</int> </value>
......@@ -83,16 +107,24 @@
</item>
<item>
<key> <string>preferred_ooodoc_server_address</string> </key>
<value> <string>127.0.0.1</string> </value>
<value> <string>10.0.0.1</string> </value>
</item>
<item>
<key> <string>preferred_ooodoc_server_port_number</string> </key>
<value> <int>40001</int> </value>
<value> <int>23000</int> </value>
</item>
<item>
<key> <string>preferred_software_setup_resource</string> </key>
<value> <string>service_module/vifib_software_setup</string> </value>
</item>
<item>
<key> <string>preferred_subscription_assignment_category</string> </key>
<value>
<tuple>
<string>function/customer</string>
</tuple>
</value>
</item>
<item>
<key> <string>preferred_time_zone</string> </key>
<value> <string>Europe/Paris</string> </value>
......
Contains uncategorised data.
\ No newline at end of file
77
\ No newline at end of file
currency_module/EUR
document_module/1
notification_message_module/vifib*
service_module/vifib_instance_cleanup
service_module/vifib_instance_hosting
service_module/vifib_instance_setup
service_module/vifib_software_setup
service_module/vifib_usage_report
\ No newline at end of file
vifib_data
\ No newline at end of file
Nexedi SA
\ No newline at end of file
vifib_core
\ No newline at end of file
Contains categories.
\ No newline at end of file
GPL
\ No newline at end of file
77
\ No newline at end of file
currency_module/EUR
document_module/1
notification_message_module/vifib*
portal_categories/activity/**
portal_categories/base_amount/**
portal_categories/business_application/**
......@@ -34,18 +31,4 @@ portal_categories/role/**
portal_categories/salary_level/**
portal_categories/site/**
portal_categories/skill/**
portal_categories/social_form/**
service_module/vifib_instance_cleanup
service_module/vifib_instance_hosting
service_module/vifib_instance_setup
service_module/vifib_software_setup
service_module/vifib_usage_report
web_page_module/vifib*
web_site_module/cash
web_site_module/cash/**
web_site_module/erpypi
web_site_module/erpypi/**
web_site_module/fiber
web_site_module/fiber/**
web_site_module/hosting
web_site_module/hosting/**
\ No newline at end of file
portal_categories/social_form/**
\ No newline at end of file
vifib_data_category
\ No newline at end of file
0.3
\ No newline at end of file
......@@ -10,8 +10,11 @@
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
......@@ -24,7 +27,6 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -44,7 +46,6 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -52,8 +53,11 @@
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
......
......@@ -10,8 +10,11 @@
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
......@@ -24,7 +27,6 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -44,7 +46,6 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -52,8 +53,11 @@
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
......
......@@ -24,6 +24,7 @@
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
......@@ -42,6 +43,8 @@
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
......
......@@ -24,6 +24,7 @@
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
......@@ -42,6 +43,8 @@
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
......
......@@ -10,8 +10,11 @@
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
......@@ -24,7 +27,6 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -44,7 +46,6 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -52,8 +53,11 @@
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
......
......@@ -10,8 +10,11 @@
<key> <string>_Access_contents_information_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
......@@ -24,7 +27,6 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -44,7 +46,6 @@
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
......@@ -52,8 +53,11 @@
<key> <string>_View_Permission</string> </key>
<value>
<tuple>
<string>Anonymous</string>
<string>Assignee</string>
<string>Assignor</string>
<string>Associate</string>
<string>Auditor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
......
......@@ -73,7 +73,7 @@
</item>
<item>
<key> <string>custom_render_method_id</string> </key>
<value> <string>WebSection_viewMyAccountRender</string> </value>
<value> <string>ERP5Site_viewNewPersonCredentialUpdateDialog</string> </value>
</item>
<item>
<key> <string>description</string> </key>
......
Nexedi SA
\ No newline at end of file
vifib_core
\ No newline at end of file
Contains web sites and pages..
\ No newline at end of file
GPL
\ No newline at end of file
None
\ No newline at end of file
78
\ No newline at end of file
web_page_module/vifib*
web_site_module/cash
web_site_module/cash/**
web_site_module/erpypi
web_site_module/erpypi/**
web_site_module/fiber
web_site_module/fiber/**
web_site_module/hosting
web_site_module/hosting/**
\ No newline at end of file
vifib_data_web
\ No newline at end of file
0.3
\ No newline at end of file
portal_categories/product_line/** does not work
\ No newline at end of file
Contains web sites.
\ No newline at end of file
76
\ No newline at end of file
vifib_datas
\ No newline at end of file
<local_roles_item>
<local_roles>
<role id='ERP5TypeTestCase'>
<item>Owner</item>
</role>
<role id='customer'>
<item>Auditor</item>
<item>Author</item>
</role>
</local_roles>
</local_roles_item>
\ No newline at end of file
<type_roles>
<role id='Auditor; Author'>
<property id='title'>Vifib Customer</property>
<multi_property id='category'>function/customer</multi_property>
<multi_property id='base_category'>function</multi_property>
</role>
</type_roles>
\ No newline at end of file
computer_module
computer_module/test_computer
credential_update_module
currency_module
currency_module/EUR
hosting_subscription_module
......
......@@ -28,4 +28,5 @@ software_instance_module
software_product_module
software_product_module/test_software_product
software_release_module
software_release_module/test_software_release
\ No newline at end of file
software_release_module/test_software_release
credential_update_module
Assignment
Computer
Computer Module
Credential Update Module
Currency
Currency Module
Hosting Subscription
......
Assignment
Computer
Computer Module
Credential Update Module
Currency
Currency Module
Hosting Subscription
......
......@@ -62,7 +62,8 @@ software_title = kwargs["software_title"]\n
software_type = kwargs.get("software_type") or "RootSoftwareInstance"\n
instance_xml = kwargs["instance_xml"]\n
sla_xml = kwargs.get("sla_xml") or ""\n
is_slave = kwargs.get(\'slave\', False)\n
is_slave = kwargs.get("slave", False)\n
state = kwargs.get("state") or "started"\n
\n
sale_order_portal_type = "Sale Order"\n
sale_order_line_portal_type = "Sale Order Line"\n
......@@ -113,6 +114,10 @@ if (request_software_instance is None):\n
title=software_title,\n
activate_kw={\'tag\': tag},\n
)\n
if state == \'started\':\n
software_instance.startRequested()\n
elif state == \'stopped\':\n
software_instance.stopRequested() \n
\n
software_release_document = context.portal_catalog.getResultValue(\n
portal_type=\'Software Release\',\n
......@@ -178,6 +183,12 @@ else:\n
sla_xml=sla_xml,\n
activate_kw={\'tag\': tag},\n
)\n
if state == \'started\':\n
request_software_instance.startRequested()\n
request_software_instance.activate(after_tag=tag).requestStartComputerPartition()\n
elif state == \'stopped\':\n
request_software_instance.stopRequested()\n
request_software_instance.activate(after_tag=tag).requestStopComputerPartition()\n
]]></string> </value>
......
......@@ -116,6 +116,7 @@ REQUIRED_BT5_ID_LIST = (\n
\'vifib_web\',\n
\'vifib_l10n_fr\',\n
\'vifib_erp5\',\n
\'vifib_data_web\',\n
)\n
\n
INTEGRITY_VERIFICATION_SCRIPT_ID_LIST = (\'ERP5Site_verifyUpgradeIntegrity\',\n
......
18
\ No newline at end of file
19
\ No newline at end of file
......@@ -90,11 +90,32 @@
</div>\n
<div class="field forgotten_password">\n
<label>&nbsp;</label>\n
<div class="input">\n
<a tal:attributes="href string:${here/portal_url}/portal_password/PasswordTool_viewEmailPassword"\n
i18n:translate="" i18n:domain="ui">I forgot my password!</a>\n
</div>\n
<div class="field nolabel validate widthAuto" title="">\n
\n
<label>\n
Join\n
\n
\n
</label>\n
<div class="input"><input class="nolabel validate widthAuto" src="" name="ERP5Site_viewCredentialRequestForm:method" value="Join" type="submit" /></div>\n
\n
\n
\n
</div>\n
</div>\n
<div class="field nolabel cancel widthAuto" title="">\n
\n
\n
<label>\n
Lost password?\n
\n
\n
</label>\n
<div class="input"><input class="nolabel cancel widthAuto" src="" name="ERP5Site_viewCredentialRecoveryLoginDialog:method" value="Lost password?" type="submit" /></div>\n
\n
\n
\n
</div>\n
</fieldset>\n
<script type="text/javascript">setFocus()</script>\n
<p i18n:translate="" i18n:domain="ui">Having trouble logging in? Make sure to enable cookies in your web browser.</p>\n
......@@ -104,8 +125,7 @@
</tal:block>\n
</tal:block>\n
</tal:block>\n
</tal:block>\n
</tal:block>
]]></unicode> </value>
</item>
......
erp5_web
erp5_commerce
erp5_credential
erp5_dms
vifib_crm
erp5_jquery
erp5_km
erp5_commerce
erp5_web
vifib_crm
vifib_forge_release
vifib_software_pdm
\ No newline at end of file
287
\ No newline at end of file
292
\ No newline at end of file
......@@ -41,6 +41,9 @@ REQUIRED_RULE_REFERENCE_LIST = [
'default_order_rule',
]
REQUIRED_NOTIFICATION_MESSAGE_REFERENCE_LIST = [
'crendential_request-confirmation-without-password',
]
class testVifibMixin(ERP5TypeTestCase):
"""
......@@ -103,7 +106,9 @@ class testVifibMixin(ERP5TypeTestCase):
'vifib_web',
'vifib_open_trade',
'vifib_l10n_fr',
'vifib_datas',
'vifib_data',
'vifib_data_category',
'vifib_data_web',
'vifib_erp5',
]
return result
......@@ -180,9 +185,27 @@ class testVifibMixin(ERP5TypeTestCase):
"""Configures and enables default system preference"""
default_system_preference = self.portal.portal_preferences\
.restrictedTraverse(self.getDefaultSitePreferenceId())
default_system_preference.edit(
preferred_credential_recovery_automatic_approval=1,
preferred_credential_request_automatic_approval=1,
preferred_person_credential_update_automatic_approval=1,
preferred_subscription_assignment_category=['function/customer',
'role/internal'],
)
if default_system_preference.getPreferenceState() == 'disabled':
default_system_preference.enable()
def setupNotificationModule(self):
module = self.portal.notification_message_module
isTransitionPossible = self.portal.portal_workflow.isTransitionPossible
for reference in REQUIRED_NOTIFICATION_MESSAGE_REFERENCE_LIST:
for message in module.searchFolder(portal_type='Notification Message',
reference=reference):
message = message.getObject()
if isTransitionPossible(message, 'validate'):
message.validate()
def setupRuleTool(self):
"""Validates newest version of each rule from REQUIRED_RULE_REFERENCE_LIST"""
rule_tool = self.portal.portal_rules
......@@ -252,6 +275,7 @@ class testVifibMixin(ERP5TypeTestCase):
self.setPreference()
self.setSystemPreference()
self.setupRuleTool()
self.setupNotificationModule()
self.openAssignments()
transaction.commit()
self.tic()
......
......@@ -7969,6 +7969,122 @@ class TestVifibSlapWebService(testVifibMixin):
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
########################################
# Other tests
########################################
def stepRequestCredentialFromWebSite(self, sequence, **kw):
sequence['web_user'] = '%s.%s' % (self.id(), random())
result = self.portal.ERP5Site_newCredentialRequest(\
first_name='Homer',
last_name='Simpson',
reference=sequence['web_user'],
password='secret',
default_email_text='homer.simpson@fox.com',
)
def stepSubmitCredentialRequest(self, sequence, **kw):
"""Simulates click of user in email confirmation about account"""
credential_request = self.portal.portal_catalog.getResultValue(
portal_type='Credential Request',
reference=sequence['web_user']
)
credential_request.submit()
def stepAcceptSubmittedCredentialsActiveSense(self, **kw):
self.portal.portal_alarms.accept_submitted_credentials.activeSense()
def stepLoginWebUser(self, sequence, **kw):
self.login(sequence['web_user'])
def test_person_from_credential_request_software_instance(self):
"""Checks that person created from web can use the system"""
sequence_list = SequenceList()
sequence_string = self.prepare_published_software_release + \
self.prepare_formated_computer + """
LoginTestVifibAdmin
RequestSoftwareInstallation
Tic
Logout
SlapLoginCurrentComputer
ComputerSoftwareReleaseAvailable
Tic
SlapLogout
Logout
RequestCredentialFromWebSite
Tic
LoginDefaultUser
SubmitCredentialRequest
Tic
AcceptSubmittedCredentialsActiveSense
Tic
Logout
LoginWebUser
PersonRequestSoftwareInstance
Tic
Logout
LoginDefaultUser
ConfirmOrderedSaleOrderActiveSense
Tic
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
CheckComputerPartitionInstanceSetupSalePackingListConfirmed
Logout
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
def stepPersonRequestCredentialUpdate(self, sequence, **kw):
sequence['updated_last_name'] = 'Another'
result = self.portal.ERP5Site_newPersonCredentialUpdate(
first_name='Homer',
last_name=sequence['updated_last_name'],
reference=sequence['web_user'],
password='secret',
default_email_text='homer.simpson@fox.com',
)
self.assertTrue('Credential%20Update%20Created' in result)
def stepCheckPersonUpdatedCredential(self, sequence, **kw):
person = self.portal.ERP5Site_getAuthenticatedMemberPersonValue(sequence[
'web_user'])
self.assertEqual(sequence['updated_last_name'], person.getLastName())
def test_person_credential_update(self):
"""Checks that Credential Update works in vifib environment."""
sequence_list = SequenceList()
sequence_string = """
Logout
RequestCredentialFromWebSite
Tic
LoginDefaultUser
SubmitCredentialRequest
Tic
AcceptSubmittedCredentialsActiveSense
Tic
Logout
LoginWebUser
PersonRequestCredentialUpdate
Tic
Logout
LoginDefaultUser
AcceptSubmittedCredentialsActiveSense
Tic
LoginWebUser
CheckPersonUpdatedCredential
Logout
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
# class IComputerPartition
# def started():
# def stopped():
......
......@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
import glob
import os
version = '0.4-dev'
version = '0.8'
name = 'slapos.core'
long_description = open("README.txt").read() + "\n" + \
open("CHANGES.txt").read() + "\n"
......@@ -46,6 +46,7 @@ setup(name=name,
entry_points={
'console_scripts': [
'slapconsole = slapos.console:run',
'slapos-request = slapos.console:request',
'slapformat = slapos.format:main',
'slapgrid = slapos.grid.slapgrid:run',
'slapgrid-sr = slapos.grid.slapgrid:runSoftwareRelease',
......
[slapos]
software_root = /opt/slapgrid
instance_root = /srv/slapgrid
master_url = http://www.vifib.com/
master_url = https://slap.vifib.com/
computer_id = your computer id
buildout = /path/to/buildout/binary
......@@ -20,3 +20,27 @@ host = 127.0.0.1
port = 5000
# You could also specify: /path/to/file
database_uri = :memory:
[slapconsole]
cert_file = certificate file location coming from your slapos master account
key_file = key file location coming from your slapos master account
# Below are softwares supported by Vifib
alias = kvm https://svn.erp5.org/repos/vifib/public/trunk/software_release/kvm/software.cfg
nbd https://svn.erp5.org/repos/vifib/public/trunk/software_release/nbdserver/software.cfg
kvm+ https://svn.erp5.org/repos/vifib/public/trunk/software_release/kvm+/software.cfg
testnode http://git.erp5.org/gitweb/slapos.git/blob_plain/testnode:/software/testnode/software.cfg
nosqltester http://git.erp5.org/gitweb/slapos.git/blob_plain/refs/heads/nosqltestbed:/software/nosqltestbed/software.cfg
slaposwebrunner https://svn.erp5.org/repos/vifib/public/trunk/software_release/runner/software.cfg
lightforum https://svn.erp5.org/repos/public/slapos/trunk/software_release.contribution/lightforum.Christophe.Lefloch/software.cfg
factux https://www.tiolive.com/vifib/P-OSOE.Factux.Wilfried.Rodrigues/Base_download
joomla https://svn.erp5.org/repos/public/slapos/trunk/software_release.contribution/joomla.Christophe.Laroulandie/software.cfg
dotclear https://svn.erp5.org/repos/public/slapos/trunk/software_release.contribution/dotclear.Kinwai.YIP/software.cfg
respest https://www.tiolive.com/vifib/P-OSOE.Respest.BENHAMED/Base_download
erp5scalabilitytestbed http://git.erp5.org/gitweb/slapos.git/blob_plain/erp5scalabilitytestbed:/software/erp5scalabilitytestbed/software.cfg
zabbixagent http://git.erp5.org/gitweb/slapos.git/blob_plain/refs/tags/slapos-0.5:/software/zabbix-agent/software.cfg
mysql-5.1 http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/mysql-5.1/software.cfg
mariadb http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/mariadb/software.cfg
memcached http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/memcached/software.cfg
kumofs http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/kumofs/software.cfg
erp5 http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/erp5/software.cfg
erp5_branch http://git.erp5.org/gitweb/slapos.git/blob_plain/refs/heads/erp5:/software/erp5/software.cfg
\ No newline at end of file
......@@ -25,5 +25,143 @@
#
##############################################################################
import slapos.slap.slap
from slapos.slap import ResourceNotReady
import sys
from optparse import OptionParser, Option
import ConfigParser
class Parser(OptionParser):
"""
Parse all arguments.
"""
def __init__(self, usage=None, version=None):
"""
Initialize all options possibles.
"""
OptionParser.__init__(self, usage=usage, version=version,
option_list=[
Option("-u", "--master_url",
default=None,
action="store",
help="Url of SlapOS Master to use."),
Option("-k", "--key_file",
action="store",
help="SSL Authorisation key file."),
Option("-c", "--cert_file",
action="store",
help="SSL Authorisation certificate file.")
])
def check_args(self):
"""
Check arguments
"""
(options, args) = self.parse_args()
if len(args) == 0:
self.error("Incorrect number of arguments")
return options, args
class Config:
def setConfig(self, option_dict, configuration_file_path):
"""
Set options given by parameters.
"""
# Set options parameters
for option, value in option_dict.__dict__.items():
setattr(self, option, value)
# Load configuration file
configuration_parser = ConfigParser.SafeConfigParser()
configuration_parser.read(configuration_file_path)
# Merges the arguments and configuration
for section in ("slapconsole",):
configuration_dict = dict(configuration_parser.items(section))
for key in configuration_dict:
if not getattr(self, key, None):
setattr(self, key, configuration_dict[key])
configuration_dict = dict(configuration_parser.items('slapos'))
setattr(self, 'master_url', configuration_dict['master_url'])
if not self.master_url:
raise ValueError('master_url is required.')
def init(config):
"""Initialize Slap instance, connect to server and create
aliases to common software releases"""
slap = slapos.slap.slap()
slap.initializeConnection(config.master_url,
key_file=config.key_file, cert_file=config.cert_file)
local = globals().copy()
local['slap'] = slap
# Create aliases as global variables
alias = config.alias.split('\n')
software_list = []
for software in alias:
if software is not '':
name, url = software.split(' ')
software_list.append(name)
local[name] = url
# Create global variable too see available aliases
local['software_list'] = software_list
# Create global shortcut functions to request instance and software
local['request'] = lambda software_release, reference: \
slap.registerOpenOrder().request(software_release, reference)
local['supply'] = lambda software_release, computer: \
slap.registerSupply().supply(software_release, computer)
return local
def request():
"""Ran when invoking slapos-request"""
# Parse arguments
usage = """usage: %s [options] CONFIGURATION_FILE SOFTWARE_INSTANCE INSTANCE_REFERENCE
slapos-request allows you to request slapos instances.""" % sys.argv[0]
config = Config()
arguments = Parser(usage=usage).check_args()[1]
config.setConfig(*Parser(usage=usage).check_args())
local = init(config)
# Request instance
# XXX-Cedric : support things like :
# --instance-type std --configuration-size 23 --computer-region europe/france
# XXX-Cedric : add support for xml_parameter
software_url = arguments[1]
partition_reference = arguments[2]
print("Requesting %s..." % software_url)
if software_url in local:
software_url = local[software_url]
try:
partition = local['slap'].registerOpenOrder().request(software_url,
partition_reference)
print("Instance requested.\nState is : %s.\nYou can "
"rerun to get up-to-date informations." % (
partition.getState()))
# XXX-Cedric : provide a way for user to fetch parameter, url, object, etc
except ResourceNotReady:
print("Instance requested. Master is provisionning it. Please rerun in a "
"couple of minutes to get connection informations")
exit(2)
def run():
__import__("code").interact(banner="", local=globals())
"""Ran when invoking slapconsole"""
# Parse arguments
usage = """usage: %s [options] CONFIGURATION_FILE
slapconsole allows you interact with slap API. You can play with the global
"slap" object and with the global "request" method.
examples :
>>> # Request instance
>>> request(kvm, "myuniquekvm")
>>> # Request software installation on owned computer
>>> supply(kvm, "mycomputer")
>>> # Fetch instance informations on already launched instance
>>> request(kvm, "myuniquekvm").getConnectionParameter("url")""" % sys.argv[0]
config = Config()
config.setConfig(*Parser(usage=usage).check_args())
local = init(config)
__import__("code").interact(banner="", local=local)
......@@ -314,53 +314,66 @@ class Computer:
os.chown(self.software_root, slapsoft_pw.pw_uid, slapsoft_pw.pw_gid)
os.chmod(self.software_root, 0755)
for partition in self.partition_list:
# Reconstructing User's
partition.path = os.path.join(self.instance_root, partition.reference)
partition.user.setPath(partition.path)
partition.user.additional_group_list = [slapsoft.name]
if alter_user:
partition.user.create()
# Reconstructing Tap
if partition.user and partition.user.isAvailable():
owner = partition.user
else:
owner = User('root')
if alter_network:
partition.tap.createWithOwner(owner)
self.bridge.addTap(partition.tap)
# Reconstructing partition's directory
partition.createPath(alter_user)
# Reconstructing partition's address
# There should be two addresses on each Computer Partition:
# * global IPv6
# * local IPv4, took from slapformat:ipv4_local_network
if len(partition.address_list) == 0:
# regenerate
partition.address_list.append(self.bridge.addIPv4LocalAddress())
partition.address_list.append(self.bridge.addAddr())
elif alter_network:
# regenerate list of addresses
old_partition_address_list = partition.address_list
partition.address_list = []
if len(old_partition_address_list) != 2:
raise ValueError('There should be exactly 2 stored addresses')
if not any([netaddr.valid_ipv6(q['addr']) for q in old_partition_address_list]):
raise ValueError('Not valid ipv6 addresses loaded')
if not any([netaddr.valid_ipv4(q['addr']) for q in old_partition_address_list]):
raise ValueError('Not valid ipv6 addresses loaded')
for address in old_partition_address_list:
if netaddr.valid_ipv6(address['addr']):
partition.address_list.append(self.bridge.addAddr(address['addr'],
address['netmask']))
elif netaddr.valid_ipv4(address['addr']):
partition.address_list.append(self.bridge.addIPv4LocalAddress(address['addr']))
try:
for partition_index, partition in enumerate(self.partition_list):
# Reconstructing User's
partition.path = os.path.join(self.instance_root, partition.reference)
partition.user.setPath(partition.path)
partition.user.additional_group_list = [slapsoft.name]
if alter_user:
partition.user.create()
# Reconstructing Tap
if partition.user and partition.user.isAvailable():
owner = partition.user
else:
owner = User('root')
if alter_network:
# In case it has to be attached to the TAP network device, only one
# is necessary for the bridge to assert carrier
if self.bridge.attach_to_tap and partition_index == 0:
partition.tap.createWithOwner(owner, attach_to_tap=True)
else:
raise ValueError('Address %r is incorrect' % address['addr'])
partition.tap.createWithOwner(owner)
self.bridge.addTap(partition.tap)
# Reconstructing partition's directory
partition.createPath(alter_user)
# Reconstructing partition's address
# There should be two addresses on each Computer Partition:
# * global IPv6
# * local IPv4, took from slapformat:ipv4_local_network
if len(partition.address_list) == 0:
# regenerate
partition.address_list.append(self.bridge.addIPv4LocalAddress())
partition.address_list.append(self.bridge.addAddr())
elif alter_network:
# regenerate list of addresses
old_partition_address_list = partition.address_list
partition.address_list = []
if len(old_partition_address_list) != 2:
raise ValueError('There should be exactly 2 stored addresses')
if not any([netaddr.valid_ipv6(q['addr']) for q in old_partition_address_list]):
raise ValueError('Not valid ipv6 addresses loaded')
if not any([netaddr.valid_ipv4(q['addr']) for q in old_partition_address_list]):
raise ValueError('Not valid ipv6 addresses loaded')
for address in old_partition_address_list:
if netaddr.valid_ipv6(address['addr']):
partition.address_list.append(self.bridge.addAddr(address['addr'],
address['netmask']))
elif netaddr.valid_ipv4(address['addr']):
partition.address_list.append(self.bridge.addIPv4LocalAddress(address['addr']))
else:
raise ValueError('Address %r is incorrect' % address['addr'])
finally:
if self.bridge.attach_to_tap:
try:
self.partition_list[0].tap.detach()
except IndexError:
pass
class Partition:
"Represent a computer partition"
......@@ -461,8 +474,16 @@ class User:
except KeyError:
return False
import struct
import fcntl
import errno
import threading
class Tap:
"Tap represent a tap interface on the system"
IFF_TAP = 0x0002
TUNSETIFF = 0x400454ca
KEEP_TAP_ATTACHED_EVENT = threading.Event()
def __init__(self, tap_name):
"""
......@@ -476,7 +497,58 @@ class Tap:
def __getinitargs__(self):
return (self.name,)
def createWithOwner(self,owner):
def attach(self):
"""
Attach to the TAP interface, meaning that it just opens the TAP interface
and wait for the caller to notify that it can be safely detached.
Linux distinguishes administrative and operational state of an network
interface. The former can be set manually by running ``ip link set dev
<dev> up|down'', whereas the latter states that the interface can actually
transmit data (for a wired network interface, it basically means that
there is carrier, e.g. the network cable is plugged into a switch for
example).
In order to be able to check the uniqueness of IPv6 address assigned to
the bridge, the network interface must be up from an administrative *and*
operational point of view.
However, from Linux 2.6.39, the bridge reflects the state of the
underlying device (e.g. the bridge asserts carrier if at least one of its
ports has carrier) whereas it always asserted carrier before. This should
work fine for "real" network interface, but will not work properly if the
bridge only binds TAP interfaces, which, from 2.6.36, reports carrier only
and only if an userspace program is attached.
"""
tap_fd = os.open("/dev/net/tun", os.O_RDWR)
try:
# Attach to the TAP interface which has previously been created
fcntl.ioctl(tap_fd, self.TUNSETIFF,
struct.pack("16sI", self.name, self.IFF_TAP))
except IOError, error:
# If EBUSY, it means another program is already attached, thus just
# ignore it...
if error.errno != errno.EBUSY:
os.close(tap_fd)
raise
else:
# Block until the caller send an event stating that the program can be
# now detached safely, thus bringing down the TAP device (from 2.6.36)
# and the bridge at the same time (from 2.6.39)
self.KEEP_TAP_ATTACHED_EVENT.wait()
finally:
os.close(tap_fd)
def detach(self):
"""
Detach to the TAP network interface by notifying the thread which attach
to the TAP and closing the TAP file descriptor
"""
self.KEEP_TAP_ATTACHED_EVENT.set()
def createWithOwner(self, owner, attach_to_tap=False):
"""
Create a tap interface on the system.
......@@ -497,6 +569,9 @@ class Tap:
callAndRead(['tunctl', '-t', self.name, '-u', owner.name])
callAndRead(['ip', 'link', 'set', self.name, 'up'])
if attach_to_tap:
threading.Thread(target=self.attach).start()
return True
class Bridge:
......@@ -511,6 +586,11 @@ class Bridge:
self.name = str(name)
self.ipv4_local_network = ipv4_local_network
# Attach to TAP network interface, only if the bridge interface does not
# report carrier
returncode, result = callAndRead(['ip', 'addr', 'list', self.name])
self.attach_to_tap = 'DOWN' in result.split('\n', 1)[0]
def __getinitargs__(self):
return (self.name,)
......@@ -525,8 +605,12 @@ class Bridge:
def getGlobalScopeAddressList(self):
"""Returns currently configured global scope IPv6 addresses"""
address_list = [q for q in netifaces.ifaddresses(self.name)[socket.AF_INET6]
if isGlobalScopeAddress(q['addr'].split('%')[0])]
try:
address_list = [q for q in netifaces.ifaddresses(self.name)[socket.AF_INET6]
if isGlobalScopeAddress(q['addr'].split('%')[0])]
except KeyError:
raise ValueError("%s must have at least one IPv6 address assigned" % \
self.name)
# XXX: Missing implementation of Unique Local IPv6 Unicast Addresses as
# defined in http://www.rfc-editor.org/rfc/rfc4193.txt
# XXX: XXX: XXX: IT IS DISALLOWED TO IMPLEMENT link-local addresses as
......
......@@ -29,7 +29,9 @@ import os
import shutil
import subprocess
import pkg_resources
import shutil
import stat
import tempfile
from supervisor import xmlrpc
import xmlrpclib
import pwd
......@@ -63,25 +65,30 @@ class Software(object):
self.logger.info("Installing software release %s..." % self.url)
if not os.path.isdir(self.software_path):
os.mkdir(self.software_path)
extends_cache = tempfile.mkdtemp()
if os.getuid() == 0:
# In case when running as root copy ownership, to simplify logic
root_stat_info = os.stat(self.software_root)
for path in [self.software_path]:
for path in [self.software_path, extends_cache]:
path_stat_info = os.stat(path)
if root_stat_info.st_uid != path_stat_info.st_uid or\
root_stat_info.st_gid != path_stat_info.st_gid:
os.chown(path, root_stat_info.st_uid,
root_stat_info.st_gid)
buildout_parameter_list = [
'buildout:directory=%s' % self.software_path,
'-c', self.url]
bootstrapBuildout(self.software_path, self.buildout,
additional_buildout_parametr_list=buildout_parameter_list,
console=self.console)
launchBuildout(self.software_path,
os.path.join(self.software_path, 'bin', 'buildout'),
additional_buildout_parametr_list=buildout_parameter_list,
console=self.console)
try:
buildout_parameter_list = [
'buildout:extends-cache=%s' % extends_cache,
'buildout:directory=%s' % self.software_path,
'-c', self.url]
bootstrapBuildout(self.software_path, self.buildout,
additional_buildout_parametr_list=buildout_parameter_list,
console=self.console)
launchBuildout(self.software_path,
os.path.join(self.software_path, 'bin', 'buildout'),
additional_buildout_parametr_list=buildout_parameter_list,
console=self.console)
finally:
shutil.rmtree(extends_cache)
def remove(self):
"""Removes the part that was installed.
......
......@@ -228,14 +228,26 @@ def bootstrapBuildout(path, buildout=None,
gid = stat_info.st_gid
invocation_list = [sys.executable, '-S']
kw = dict()
if buildout is not None:
invocation_list.append(buildout)
invocation_list.extend(additional_buildout_parametr_list)
else:
logger.warning('Using old style bootstrap of included bootstrap file. '
'Consider setting buildout binary location.')
invocation_list.append(pkg_resources.resource_filename(__name__,
'zc.buildout-bootstap.py'))
invocation_list.extend(additional_buildout_parametr_list)
try:
import zc.buildout
except ImportError:
logger.warning('Using old style bootstrap of included bootstrap file. '
'Consider setting buildout binary location.')
invocation_list.append(pkg_resources.resource_filename(__name__,
'zc.buildout-bootstap.py'))
invocation_list.extend(additional_buildout_parametr_list)
else:
# buildout is importable, so use this one
invocation_list.extend(["-c", "import sys ; sys.path=" + str(sys.path) +
" ; import zc.buildout.buildout ; sys.argv[1:1]=" + \
repr(additional_buildout_parametr_list + ['bootstrap']) + " ; "
"zc.buildout.buildout.main()"])
if buildout is not None:
invocation_list.append('bootstrap')
try:
......@@ -243,7 +255,6 @@ def bootstrapBuildout(path, buildout=None,
logger.debug('Set umask from %03o to %03o' % (umask, SAFE_UMASK))
logger.debug('Invoking: %r in directory %r' % (' '.join(invocation_list),
path))
kw = dict()
if not console:
kw.update(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
process_handler = SlapPopen(invocation_list,
......
......@@ -141,7 +141,7 @@ class Supply(SlapDocument):
def supply(self, software_release, computer_guid=None):
self._connection_helper.POST('/supplySupply', {
'url': software_release,
'url': software_release,
'computer_id': computer_guid})
class OpenOrder(SlapDocument):
......@@ -160,7 +160,7 @@ class OpenOrder(SlapDocument):
'partition_reference': partition_reference,
'partition_parameter_xml': xml_marshaller.dumps(partition_parameter_kw),
'filter_xml': xml_marshaller.dumps(filter_kw),
'state': state,
'state': xml_marshaller.dumps(state),
}
if software_type is not None:
request_dict['software_type'] = software_type
......
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