Commit 42e72e67 authored by Alain Takoudjou's avatar Alain Takoudjou

Merge branch 'master' into operation-control

parents 64c208f6 14904721
Changes Changes
======= =======
1.2.1 (2014-08-21)
------------------
* slapproxy: add automatic migration to new database schema if needed.
1.2.0 (2014-08-18)
------------------
Note: not officially released as egg.
* slapproxy: add correct support for slaves, instance_guid, state.
* slapproxy: add getComputerPartitionStatus dummy support.
* slapproxy: add multi-nodes support
1.1.2 (2014-06-02) 1.1.2 (2014-06-02)
------------------ ------------------
......
...@@ -50,10 +50,13 @@ ...@@ -50,10 +50,13 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>portal = context.getPortalObject()\n <value> <string encoding="cdata"><![CDATA[
portal = context.getPortalObject()\n
\n \n
category_public = portal.restrictedTraverse("portal_categories/allocation_scope/open/public", None)\n category_public = portal.restrictedTraverse("portal_categories/allocation_scope/open/public", None)\n
category_friend = portal.restrictedTraverse("portal_categories/allocation_scope/open/friend", None)\n category_friend = portal.restrictedTraverse("portal_categories/allocation_scope/open/friend", None)\n
category_personal = portal.restrictedTraverse("portal_categories/allocation_scope/open/personal", None)\n
\n \n
if category_public is not None:\n if category_public is not None:\n
portal.portal_catalog.searchAndActivate(\n portal.portal_catalog.searchAndActivate(\n
...@@ -63,8 +66,23 @@ if category_public is not None:\n ...@@ -63,8 +66,23 @@ if category_public is not None:\n
method_id=\'Computer_checkAndUpdateAllocationScope\',\n method_id=\'Computer_checkAndUpdateAllocationScope\',\n
activate_kw={\'tag\': tag}\n activate_kw={\'tag\': tag}\n
)\n )\n
\n
if category_personal is not None:\n
portal.portal_catalog.searchAndActivate(\n
portal_type=\'Computer\', \n
validation_state=\'validated\', \n
modification_date=(DateTime() - 30).strftime(\'<=%Y/%m/%d\'), \n
order_by=((\'modification_date\', "ASC"), ), \n
default_allocation_scope_uid=category_personal.getUid(), \n
left_join_list=[\'aggregate_related_uid\'], \n
aggregate_related_uid=None,\n
method_id=\'Computer_checkAndUpdatePersonalAllocationScope\',\n
activate_kw={\'tag\': tag})\n
\n
context.activate(after_tag=tag).getId()\n context.activate(after_tag=tag).getId()\n
</string> </value>
]]></string> </value>
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
......
...@@ -57,7 +57,11 @@ portal = context.getPortalObject()\n ...@@ -57,7 +57,11 @@ portal = context.getPortalObject()\n
allocation_scope = computer.getAllocationScope()\n allocation_scope = computer.getAllocationScope()\n
computer_reference = computer.getReference()\n computer_reference = computer.getReference()\n
\n \n
if allocation_scope not in [\'open/public\', \'open/friend\']:\n if allocation_scope not in [\'open/public\', \'open/friend\', \'open/personal\']:\n
return\n
\n
if allocation_scope == target_allocation_scope:\n
# already changed\n
return\n return\n
\n \n
person = computer.getSourceAdministrationValue(portal_type="Person")\n person = computer.getSourceAdministrationValue(portal_type="Person")\n
...@@ -65,17 +69,15 @@ if not person:\n ...@@ -65,17 +69,15 @@ if not person:\n
return\n return\n
\n \n
if not person.Person_isServiceProvider():\n if not person.Person_isServiceProvider():\n
#Turn this computer allocation scope to \'open/personal\'\n
edit_kw = {\n edit_kw = {\n
\'allocation_scope\': \'open/personal\',\n \'allocation_scope\': target_allocation_scope,\n
}\n }\n
computer.edit(**edit_kw)\n
\n \n
# Create a ticket (or re-open it) for this issue!\n # Create a ticket (or re-open it) for this issue!\n
support_request = None\n support_request = None\n
request_title = \'We have changed allocation scope for %s\' % computer_reference\n request_title = \'We have changed allocation scope for %s\' % computer_reference\n
request_description = \'Allocation scope has been changed back to \' \\\n request_description = \'Allocation scope has been changed to \' \\\n
\'open/personal for %s\' % computer_reference\n \'%s for %s\' % (target_allocation_scope, computer_reference)\n
\n \n
support_request_url = context.Base_generateSupportRequestForSlapOS(\n support_request_url = context.Base_generateSupportRequestForSlapOS(\n
request_title,\n request_title,\n
...@@ -91,7 +93,7 @@ if not person.Person_isServiceProvider():\n ...@@ -91,7 +93,7 @@ if not person.Person_isServiceProvider():\n
support_request = portal.portal_catalog.getResultValue(\n support_request = portal.portal_catalog.getResultValue(\n
portal_type = \'Support Request\',\n portal_type = \'Support Request\',\n
title = request_title,\n title = request_title,\n
simulation_state = \'suspended\',\n simulation_state = [\'suspended\', \'open\'],\n
source_project_uid = computer.getUid()\n source_project_uid = computer.getUid()\n
)\n )\n
if support_request is None:\n if support_request is None:\n
...@@ -100,7 +102,7 @@ if not person.Person_isServiceProvider():\n ...@@ -100,7 +102,7 @@ if not person.Person_isServiceProvider():\n
\n \n
# Send notification message\n # Send notification message\n
notification_message = portal.portal_notifications.getDocumentValue(\n notification_message = portal.portal_notifications.getDocumentValue(\n
reference=\'slapos-crm-computer_allocation_scope.notification\')\n reference=notification_message_reference)\n
\n \n
if notification_message is not None:\n if notification_message is not None:\n
mapping_dict = {\'computer_title\':computer.getTitle(),\n mapping_dict = {\'computer_title\':computer.getTitle(),\n
...@@ -111,13 +113,16 @@ if not person.Person_isServiceProvider():\n ...@@ -111,13 +113,16 @@ if not person.Person_isServiceProvider():\n
else:\n else:\n
message = request_description\n message = request_description\n
\n \n
support_request.SupportRequest_trySendNotificationMessage(request_title,\n event = support_request.SupportRequest_trySendNotificationMessage(request_title,\n
message, person.getRelativeUrl())\n message, person.getRelativeUrl())\n
\n
if event is not None:\n
computer.edit(**edit_kw)\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string></string> </value> <value> <string>target_allocation_scope=\'open/personal\', notification_message_reference=\'slapos-crm-computer_allocation_scope.notification\'</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
<?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.Computer_checkAndUpdateAllocationScope(\n
target_allocation_scope = \'close/termination\',\n
notification_message_reference=\'slapos-crm-computer_personal_allocation_scope.notification\')\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>**kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Computer_checkAndUpdatePersonalAllocationScope</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -1867,7 +1867,8 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin): ...@@ -1867,7 +1867,8 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin):
'context.portal_workflow.doActionFor(' \ 'context.portal_workflow.doActionFor(' \
'context, action="edit_action", ' \ 'context, action="edit_action", ' \
'comment="Visited by SupportRequest_trySendNotificationMessage ' \ 'comment="Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s %s" % (message_title, message, source_relative_url, interval_of_day))') '%s %s %s %s" % (message_title, message, source_relative_url, interval_of_day))\n' \
'return 1')
def test_computerNotAllowedAllocationScope_OpenPublic(self): def test_computerNotAllowedAllocationScope_OpenPublic(self):
computer = self._makeComputer(self.new_id) computer = self._makeComputer(self.new_id)
person = computer.getSourceAdministrationValue() person = computer.getSourceAdministrationValue()
...@@ -1899,7 +1900,8 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin): ...@@ -1899,7 +1900,8 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin):
'context.portal_workflow.doActionFor(' \ 'context.portal_workflow.doActionFor(' \
'context, action="edit_action", ' \ 'context, action="edit_action", ' \
'comment="Visited by SupportRequest_trySendNotificationMessage ' \ 'comment="Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s %s" % (message_title, message, source_relative_url, interval_of_day))') '%s %s %s %s" % (message_title, message, source_relative_url, interval_of_day))\n' \
'return 1')
def test_computerNotAllowedAllocationScope_OpenFriend(self): def test_computerNotAllowedAllocationScope_OpenFriend(self):
computer = self._makeComputer(self.new_id) computer = self._makeComputer(self.new_id)
person = computer.getSourceAdministrationValue() person = computer.getSourceAdministrationValue()
...@@ -1922,6 +1924,38 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin): ...@@ -1922,6 +1924,38 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin):
'Test NM content\n%s\n' % computer.getReference(), person.getRelativeUrl(), '1'), 'Test NM content\n%s\n' % computer.getReference(), person.getRelativeUrl(), '1'),
ticket.workflow_history['edit_workflow'][-1]['comment']) ticket.workflow_history['edit_workflow'][-1]['comment'])
@simulate('NotificationTool_getDocumentValue',
'reference=None',
'assert reference == "slapos-crm-computer_personal_allocation_scope.notification"\n' \
'return context.restrictedTraverse(' \
'context.REQUEST["test_computerToCloseAllocationScope_OpenPersonal"])')
@simulate('SupportRequest_trySendNotificationMessage',
'message_title, message, source_relative_url, interval_of_day=1',
'context.portal_workflow.doActionFor(' \
'context, action="edit_action", ' \
'comment="Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s %s" % (message_title, message, source_relative_url, interval_of_day))\n' \
'return 1')
def test_computerToCloseAllocationScope_OpenPersonal(self):
computer = self._makeComputer(self.new_id)
person = computer.getSourceAdministrationValue()
self.portal.REQUEST['test_computerToCloseAllocationScope_OpenPersonal'] = \
self._makeNotificationMessage(computer.getReference())
friend_person = self._makePerson(self.generateNewId())
computer.edit(allocation_scope='open/personal',
destination_section=friend_person.getRelativeUrl())
computer.Computer_checkAndUpdatePersonalAllocationScope()
self.tic()
self.assertEquals(computer.getAllocationScope(), 'close/termination')
ticket = self._getGeneratedSupportRequest(computer)
self.assertEquals(ticket.getSimulationState(), 'suspended')
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s %s' % \
('We have changed allocation scope for %s' % computer.getReference(),
'Test NM content\n%s\n' % computer.getReference(), person.getRelativeUrl(), '1'),
ticket.workflow_history['edit_workflow'][-1]['comment'])
def test_computerNormalAllocationScope_OpenPersonal(self): def test_computerNormalAllocationScope_OpenPersonal(self):
computer = self._makeComputer(self.new_id) computer = self._makeComputer(self.new_id)
......
...@@ -367,8 +367,6 @@ class TestSlapOSCloudSupportRequestGeneration(testSlapOSMixin): ...@@ -367,8 +367,6 @@ class TestSlapOSCloudSupportRequestGeneration(testSlapOSMixin):
self.assertEqual(event.getTitle(), title) self.assertEqual(event.getTitle(), title)
def test_Computer_checkState_empty_cache(self): def test_Computer_checkState_empty_cache(self):
computer = self._makeComputer(self.new_id) computer = self._makeComputer(self.new_id)
...@@ -838,6 +836,7 @@ portal_workflow.doActionFor(context, action='edit_action', comment='Visited by C ...@@ -838,6 +836,7 @@ portal_workflow.doActionFor(context, action='edit_action', comment='Visited by C
self.assertEqual('Visited by Computer_checkAndUpdateAllocationScope', self.assertEqual('Visited by Computer_checkAndUpdateAllocationScope',
computer.workflow_history['edit_workflow'][-1]['comment']) computer.workflow_history['edit_workflow'][-1]['comment'])
def test_Alarm_notAllowedAllocationScope_OpenFriend(self): def test_Alarm_notAllowedAllocationScope_OpenFriend(self):
computer = self._makeComputer(self.new_id) computer = self._makeComputer(self.new_id)
computer.edit(allocation_scope = 'open/friend') computer.edit(allocation_scope = 'open/friend')
...@@ -868,6 +867,52 @@ portal_workflow.doActionFor(context, action='edit_action', comment='Visited by C ...@@ -868,6 +867,52 @@ portal_workflow.doActionFor(context, action='edit_action', comment='Visited by C
self.assertNotEqual('Visited by Computer_checkAndUpdateAllocationScope', self.assertNotEqual('Visited by Computer_checkAndUpdateAllocationScope',
computer.workflow_history['edit_workflow'][-1]['comment']) computer.workflow_history['edit_workflow'][-1]['comment'])
def test_Alarm_AllowedAllocationScope_OpenPersonal_old_computer(self):
computer = self._makeComputer(self.new_id)
computer.edit(allocation_scope = 'open/personal')
def getModificationDate(self):
return DateTime() - 50
from Products.ERP5Type.Base import Base
self._simulateComputer_checkAndUpdateAllocationScope()
original_get_modification = Base.getModificationDate
Base.getModificationDate = getModificationDate
try:
self.portal.portal_alarms.slapos_crm_check_update_allocation_scope.activeSense()
self.tic()
finally:
Base.getModificationDate = original_get_modification
self._dropComputer_checkAndUpdateAllocationScope()
self.assertEqual('Visited by Computer_checkAndUpdateAllocationScope',
computer.workflow_history['edit_workflow'][-1]['comment'])
def test_Alarm_AllowedAllocationScope_OpenPersonalWithSoftwareInstallation(self):
computer = self._makeComputer(self.new_id)
computer.edit(allocation_scope = 'open/personal')
software_installation = self._makeSoftwareInstallation(
self.new_id, computer, "http://...")
def getModificationDate(self):
return DateTime() - 50
from Products.ERP5Type.Base import Base
self._simulateComputer_checkAndUpdateAllocationScope()
original_get_modification = Base.getModificationDate
Base.getModificationDate = getModificationDate
try:
self.portal.portal_alarms.slapos_crm_check_update_allocation_scope.activeSense()
self.tic()
finally:
Base.getModificationDate = original_get_modification
self._dropComputer_checkAndUpdateAllocationScope()
self.assertNotEqual('Visited by Computer_checkAndUpdateAllocationScope',
computer.workflow_history['edit_workflow'][-1]['comment'])
def _simulateHostingSubscription_checkSofwareInstanceState(self): def _simulateHostingSubscription_checkSofwareInstanceState(self):
script_name = 'HostingSubscription_checkSofwareInstanceAllocationState' script_name = 'HostingSubscription_checkSofwareInstanceAllocationState'
if script_name in self.portal.portal_skins.custom.objectIds(): if script_name in self.portal.portal_skins.custom.objectIds():
......
event_module/slapos_crm_web_message_template event_module/slapos_crm_web_message_template
person_module/allocation_tester person_module/allocation_tester
portal_alarms/slapos_check_cloud_is_full
portal_alarms/slapos_check_computer_state portal_alarms/slapos_check_computer_state
portal_alarms/slapos_check_software_instance_state portal_alarms/slapos_check_software_instance_state
portal_alarms/slapos_crm_cancel_invoice portal_alarms/slapos_crm_cancel_invoice
......
<type_roles> <type_roles>
<role id='Auditor'>
<property id='title'>Agent as auditor</property>
<property id='base_category_script'>ERP5Type_getSecurityCategoryFromContent</property>
<multi_property id='base_category'>agent</multi_property>
</role>
<role id='Assignor'> <role id='Assignor'>
<property id='title'>Group company</property> <property id='title'>Group company</property>
<multi_property id='category'>group/company</multi_property> <multi_property id='category'>group/company</multi_property>
......
...@@ -35,6 +35,10 @@ ...@@ -35,6 +35,10 @@
<type>Person</type> <type>Person</type>
<workflow>local_permission_slapos_interaction_workflow</workflow> <workflow>local_permission_slapos_interaction_workflow</workflow>
</chain> </chain>
<chain>
<type>Restricted Access Token</type>
<workflow>local_permission_slapos_interaction_workflow</workflow>
</chain>
<chain> <chain>
<type>Sale Invoice Transaction</type> <type>Sale Invoice Transaction</type>
<workflow>local_permission_slapos_interaction_workflow</workflow> <workflow>local_permission_slapos_interaction_workflow</workflow>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="InteractionDefinition" module="Products.ERP5.Interaction"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>activate_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value>
<list>
<string>Base_updateAllLocalRoles</string>
</list>
</value>
</item>
<item>
<key> <string>before_commit_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>RestrictedAccessToken_edit</string> </value>
</item>
<item>
<key> <string>method_id</string> </key>
<value>
<list>
<string>_setAgent.*</string>
</list>
</value>
</item>
<item>
<key> <string>once_per_transaction</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>portal_type_filter</string> </key>
<value>
<list>
<string>Restricted Access Token</string>
</list>
</value>
</item>
<item>
<key> <string>script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>temporary_document_disallowed</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="InteractionDefinition" module="Products.ERP5.Interaction"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>activate_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value>
<list>
<string>Base_updateAllLocalRoles</string>
</list>
</value>
</item>
<item>
<key> <string>before_commit_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>UpgradeDecision_edit</string> </value>
</item>
<item>
<key> <string>method_id</string> </key>
<value>
<list>
<string>_setDestinationSection.*</string>
</list>
</value>
</item>
<item>
<key> <string>once_per_transaction</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>portal_type_filter</string> </key>
<value>
<list>
<string>Upgrade Decision</string>
</list>
</value>
</item>
<item>
<key> <string>script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>temporary_document_disallowed</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -7,6 +7,7 @@ Integration Site | local_permission_slapos_interaction_workflow ...@@ -7,6 +7,7 @@ Integration Site | local_permission_slapos_interaction_workflow
Payment Transaction | local_permission_slapos_interaction_workflow Payment Transaction | local_permission_slapos_interaction_workflow
Payzen Event | local_permission_slapos_interaction_workflow Payzen Event | local_permission_slapos_interaction_workflow
Person | local_permission_slapos_interaction_workflow Person | local_permission_slapos_interaction_workflow
Restricted Access Token | local_permission_slapos_interaction_workflow
Sale Invoice Transaction | local_permission_slapos_interaction_workflow Sale Invoice Transaction | local_permission_slapos_interaction_workflow
Sale Packing List | local_permission_slapos_interaction_workflow Sale Packing List | local_permission_slapos_interaction_workflow
Slave Instance | local_permission_slapos_interaction_workflow Slave Instance | local_permission_slapos_interaction_workflow
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>active_sense_method_id</string> </key> <key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_checkCloudIsFull</string> </value> <value> <string>Alarm_processStoppedUpgradeDecision</string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
...@@ -22,7 +22,13 @@ ...@@ -22,7 +22,13 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>slapos_check_cloud_is_full</string> </value> <value> <string>slapos_pdm_upgrade_decision_process_stopped</string> </value>
</item>
<item>
<key> <string>periodicity_day_frequency</string> </key>
<value>
<none/>
</value>
</item> </item>
<item> <item>
<key> <string>periodicity_hour</string> </key> <key> <string>periodicity_hour</string> </key>
...@@ -32,7 +38,9 @@ ...@@ -32,7 +38,9 @@
</item> </item>
<item> <item>
<key> <string>periodicity_hour_frequency</string> </key> <key> <string>periodicity_hour_frequency</string> </key>
<value> <int>1</int> </value> <value>
<none/>
</value>
</item> </item>
<item> <item>
<key> <string>periodicity_minute</string> </key> <key> <string>periodicity_minute</string> </key>
...@@ -42,9 +50,7 @@ ...@@ -42,9 +50,7 @@
</item> </item>
<item> <item>
<key> <string>periodicity_minute_frequency</string> </key> <key> <string>periodicity_minute_frequency</string> </key>
<value> <value> <int>5</int> </value>
<none/>
</value>
</item> </item>
<item> <item>
<key> <string>periodicity_month</string> </key> <key> <string>periodicity_month</string> </key>
...@@ -70,7 +76,7 @@ ...@@ -70,7 +76,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1377608640.0</float> <float>3660.0</float>
<string>GMT</string> <string>GMT</string>
</tuple> </tuple>
</state> </state>
...@@ -87,15 +93,9 @@ ...@@ -87,15 +93,9 @@
<key> <string>portal_type</string> </key> <key> <string>portal_type</string> </key>
<value> <string>Alarm</string> </value> <value> <string>Alarm</string> </value>
</item> </item>
<item>
<key> <string>sense_method_id</string> </key>
<value>
<none/>
</value>
</item>
<item> <item>
<key> <string>title</string> </key> <key> <string>title</string> </key>
<value> <string>Check if vifib cloud is full</string> </value> <value> <string>Process Stopped Upgrade Decisions</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -51,19 +51,12 @@ ...@@ -51,19 +51,12 @@
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>portal = context.getPortalObject()\n <value> <string>portal = context.getPortalObject()\n
\n portal.portal_catalog.searchAndActivate(\n
software_release_preference = portal.portal_preferences.getPreferredSoftwareReleaseToTestForSpace()\n portal_type=\'Upgrade Decision\',\n
\n simulation_state=\'stopped\',\n
if software_release_preference != \'\':\n method_id=\'UpgradeDecision_notifyDelivered\',\n
software_release_list = software_release_preference.split("\\n")\n activate_kw={\'tag\': tag }\n
\n )\n
portal.portal_catalog.searchAndActivate(\n
portal_type = \'Software Release\',\n
url_string = software_release_list,\n
\n
method_id = \'SoftwareRelease_testForAllocation\',\n
activate_kw = {\'tag\':tag} \n
)\n
\n \n
context.activate(after_tag=tag).getId()\n context.activate(after_tag=tag).getId()\n
</string> </value> </string> </value>
...@@ -74,7 +67,7 @@ context.activate(after_tag=tag).getId()\n ...@@ -74,7 +67,7 @@ context.activate(after_tag=tag).getId()\n
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Alarm_checkCloudIsFull</string> </value> <value> <string>Alarm_processStoppedUpgradeDecision</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -74,11 +74,12 @@ if not person_url:\n ...@@ -74,11 +74,12 @@ if not person_url:\n
\n \n
upgrade_decision = portal.upgrade_decision_module.\\\n upgrade_decision = portal.upgrade_decision_module.\\\n
template_upgrade_decision.Base_createCloneDocument(batch_mode=1)\n template_upgrade_decision.Base_createCloneDocument(batch_mode=1)\n
upgrade_decision.edit(\n \n
title=title,\n upgrade_decision.edit(title=title)\n
destination_section=person_url,\n \n
destination_decision=person_url\n upgrade_decision.setDestinationSection(person_url)\n
)\n upgrade_decision.setDestinationDecision(person_url)\n
\n
decision_line_list = upgrade_decision.contentValues(\n decision_line_list = upgrade_decision.contentValues(\n
portal_type=\'Upgrade Decision Line\')\n portal_type=\'Upgrade Decision Line\')\n
if len(decision_line_list) > 0:\n if len(decision_line_list) > 0:\n
......
<?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>portal = context.getPortalObject()\n
\n
notification_message = portal.portal_notifications.getDocumentValue(\n
reference=\'slapos-upgrade-computer.notification\')\n
\n
title = "New Software available for Installation at %s" % computer.getTitle()\n
mapping_dict = {\'software_product_title\': software_product_title,\n
\'computer_title\': computer.getTitle(),\n
\'computer_reference\': computer.getReference(),\n
\'software_release_name\': software_release.getTitle(),\n
\'software_release_reference\': software_release.getReference(),\n
\'upgrade_accept_link\': \n
\'Base_acceptUpgradeDecision?reference=%s\' % reference,\n
\'upgrade_reject_link\':\n
\'Base_rejectUpgradeDecision?reference=%s\' % reference,\n
\'new_software_release_url\': software_release.getUrlString(),\n
}\n
\n
\n
if notification_message is not None:\n
message = notification_message.asEntireHTML(\n
substitution_method_parameter_dict={\'mapping_dict\': mapping_dict})\n
else:\n
raise ValueError("No Notification Message")\n
\n
return title, message\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>computer</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>UpgradeDecision_getComputerNotificationMessage</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -50,34 +50,34 @@ ...@@ -50,34 +50,34 @@
</item> </item>
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>portal = context.getPortalObject()\n <value> <string encoding="cdata"><![CDATA[
software_release = context\n
software_release_url = software_release.getUrlString()\n portal = context.getPortalObject()\n
\n \n
user = portal.person_module.allocation_tester\n hosting_subscription = context.UpgradeDecision_getHostingSubscription()\n
computer = context.UpgradeDecision_getComputer()\n
software_release = context.UpgradeDecision_getSoftwareRelease()\n
\n \n
result = user.Person_restrictMethodAsShadowUser(\n if hosting_subscription is not None:\n
shadow_document=user,\n if hosting_subscription.getUrlString() == software_release.getUrlString():\n
callable_object=user.Person_findPartition,\n return True\n
argument_list=[\n
software_release_url,\n
\'\',\n
\'Software Instance\',\n
{}\n
],\n
argument_dict={\n
\'test_mode\': True})\n
\n \n
if not result:\n elif computer is not None:\n
title = "Can\'t allocate new instances for software release %s" % software_release_url\n full_software_release_list = [si for si in \n
description = "Need more public computers that can instanciate the software release %s" % software_release_url\n portal.portal_catalog(\n
portal_type=\'Software Installation\',\n
url_string=software_release.getUrlString(),\n
default_aggregate_uid=computer.getUid(),\n
validation_state=\'validated\'\n
) if si.getSlapState() == \'start_requested\']\n
\n \n
return software_release.Base_generateSupportRequestForSlapOS(\n if len(full_software_release_list) > 0:\n
title,\n return True\n
description,\n \n
software_release.getRelativeUrl()\n return False\n
)\n
</string> </value>
]]></string> </value>
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
...@@ -85,7 +85,7 @@ if not result:\n ...@@ -85,7 +85,7 @@ if not result:\n
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>SoftwareRelease_testForAllocation</string> </value> <value> <string>UpgradeDecision_isUpgradeFinished</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
<?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>from DateTime import DateTime\n
\n
if context.getSimulationState() != \'stopped\':\n
return \n
\n
if context.UpgradeDecision_isUpgradeFinished():\n
return \n
\n
portal = context.getPortalObject()\n
\n
person = context.getDestinationDecisionValue(portal_type="Person")\n
if not person:\n
raise ValueError("Inconsistent Upgrade Decision, No Destination Decision")\n
\n
hosting_subscription = context.UpgradeDecision_getHostingSubscription()\n
computer = context.UpgradeDecision_getComputer()\n
software_release = context.UpgradeDecision_getSoftwareRelease()\n
software_product_title = software_release.getAggregateTitle(\n
portal_type="Software Product")\n
\n
reference = context.getReference()\n
\n
mapping_dict = {\n
\'software_product_title\': software_product_title,\n
\'software_release_name\': software_release.getTitle(),\n
\'software_release_reference\': software_release.getReference(),\n
\'new_software_release_url\': software_release.getUrlString(),\n
}\n
\n
if hosting_subscription is not None:\n
notification_message_reference = \'slapos-upgrade-delivered-hosting-subscription.notification\'\n
title = "Upgrade Processed for %s (%s)" % (hosting_subscription.getTitle(), \n
software_release.getReference())\n
mapping_dict.update(**{\n
\'hosting_subscription_title\': hosting_subscription.getTitle(),\n
\'old_software_release_url\': hosting_subscription.getUrlString()})\n
\n
elif computer is not None:\n
\n
notification_message_reference = \'slapos-upgrade-delivered-computer.notification\' \n
\n
title = "Upgrade processed at %s for %s" % (computer.getTitle(), software_release.getReference()) \n
mapping_dict.update(**{\'computer_title\': computer.getTitle(),\n
\'computer_reference\': computer.getReference()})\n
\n
\n
if notification_message_reference is None:\n
raise ValueError("No Notification Message")\n
\n
notification_message = portal.portal_notifications.getDocumentValue(\n
reference=notification_message_reference)\n
\n
message = notification_message.asEntireHTML(\n
substitution_method_parameter_dict={\'mapping_dict\': mapping_dict})\n
\n
event = context.SupportRequest_trySendNotificationMessage(title,\n
message, person.getRelativeUrl())\n
\n
if event is not None:\n
context.deliver()\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>**kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>UpgradeDecision_notifyDelivered</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -87,6 +87,23 @@ return %s ...@@ -87,6 +87,23 @@ return %s
upgrade_decision.workflow_history['edit_workflow'][-1]['comment']) upgrade_decision.workflow_history['edit_workflow'][-1]['comment'])
def test_alarm_upgrade_decision_process_stopped(self):
upgrade_decision = self._makeUpgradeDecision()
upgrade_decision.start()
upgrade_decision.stop()
self.tic()
self._simulateScript('UpgradeDecision_notifyDelivered')
try:
self.portal.portal_alarms.slapos_pdm_upgrade_decision_process_stopped.\
activeSense()
self.tic()
finally:
self._dropScript('UpgradeDecision_notifyDelivered')
self.assertEqual('Visited by UpgradeDecision_notifyDelivered',
upgrade_decision.workflow_history['edit_workflow'][-1]['comment'])
def test_alarm_computer_create_upgrade_decision(self): def test_alarm_computer_create_upgrade_decision(self):
computer = self._makeComputer(self.new_id) computer = self._makeComputer(self.new_id)
computer.edit(allocation_scope = 'open/public') computer.edit(allocation_scope = 'open/public')
......
...@@ -1394,6 +1394,37 @@ class TestSlapOSPDMSkins(testSlapOSMixin): ...@@ -1394,6 +1394,37 @@ class TestSlapOSPDMSkins(testSlapOSMixin):
"?portal_status_message=Upgrade%20Decision%20is%20already%20Rejected%21"), "?portal_status_message=Upgrade%20Decision%20is%20already%20Rejected%21"),
"%s contains the wrong message" % redirect_url) "%s contains the wrong message" % redirect_url)
def testUpgradeDecision_isUpgradeFinished_computer(self):
computer = self._makeComputer(self.new_id)
software_release = self._makeSoftwareRelease(self.new_id)
upgrade_decision = self._makeUpgradeDecision()
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValueList([software_release, computer])
upgrade_decision.confirm()
upgrade_decision.stop()
self.assertFalse(upgrade_decision.UpgradeDecision_isUpgradeFinished())
self._makeSoftwareInstallation(self.new_id, computer,
software_release.getUrlString())
self.tic()
self.assertTrue(upgrade_decision.UpgradeDecision_isUpgradeFinished())
def testUpgradeDecision_isUpgradeFinished_hosting_subscription(self):
hosting_subscription = self._makeHostingSubscription(self.new_id)
software_release = self._makeSoftwareRelease(self.new_id)
upgrade_decision = self._makeUpgradeDecision()
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValueList([software_release,
hosting_subscription])
upgrade_decision.confirm()
upgrade_decision.stop()
self.assertFalse(upgrade_decision.UpgradeDecision_isUpgradeFinished())
hosting_subscription.setUrlString(software_release.getUrlString())
self.assertTrue(upgrade_decision.UpgradeDecision_isUpgradeFinished())
@simulate('NotificationTool_getDocumentValue', @simulate('NotificationTool_getDocumentValue',
'reference=None', 'reference=None',
'assert reference == "slapos-upgrade-computer.notification"\n' \ 'assert reference == "slapos-upgrade-computer.notification"\n' \
...@@ -1525,3 +1556,133 @@ ${new_software_release_url}""", ...@@ -1525,3 +1556,133 @@ ${new_software_release_url}""",
self.assertEquals(event.getSimulationState(), "delivered") self.assertEquals(event.getSimulationState(), "delivered")
@simulate('NotificationTool_getDocumentValue',
'reference=None',
'assert reference == "slapos-upgrade-delivered-computer.notification"\n' \
'return context.restrictedTraverse(' \
'context.REQUEST["testUpgradeDecision_notifyDelivered_computer"])')
@simulate('UpgradeDecision_isUpgradeFinished',
'', 'return 0')
def testUpgradeDecision_notifyDelivered_computer(self):
person = self._makePerson(self.new_id)
computer = self._makeComputer(self.new_id)
software_release = self._makeSoftwareRelease(self.new_id)
software_product = self._makeSoftwareProduct(self.new_id)
software_release.setAggregateValue(software_product)
upgrade_decision = self._makeUpgradeDecision()
upgrade_decision.edit(destination_decision_value=person)
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValueList([software_release, computer])
notification_message = self.portal.notification_message_module.newContent(
portal_type="Notification Message",
title='Test NM title %s' % self.new_id,
text_content_substitution_mapping_method_id=
"NotificationMessage_getSubstitutionMappingDictFromArgument",
text_content="""${software_product_title}
${computer_title}
${computer_reference}
${software_release_name}
${software_release_reference}
${new_software_release_url}""",
content_type='text/html',
)
self.portal.REQUEST\
['testUpgradeDecision_notifyDelivered_computer'] = \
notification_message.getRelativeUrl()
self.tic()
self.assertEquals(None, upgrade_decision.UpgradeDecision_notifyDelivered())
upgrade_decision.start()
upgrade_decision.stop()
self.tic()
self.assertEquals(None, upgrade_decision.UpgradeDecision_notifyDelivered())
self.tic()
self.assertEquals(upgrade_decision.getSimulationState(), 'delivered')
self.assertEquals(len(upgrade_decision.getFollowUpRelatedValueList()), 1)
event = upgrade_decision.getFollowUpRelatedValue()
self.assertEquals(event.getTitle(),
"Upgrade processed at %s for %s" % (computer.getTitle(),
software_release.getReference()))
self.assertEqual(event.getTextContent().splitlines(),
[software_product.getTitle(), computer.getTitle(), computer.getReference(),
software_release.getTitle(), software_release.getReference(),
software_release.getUrlString()])
self.assertEquals(event.getSimulationState(), "delivered")
@simulate('NotificationTool_getDocumentValue',
'reference=None',
'assert reference == "slapos-upgrade-delivered-hosting-subscription.notification"\n' \
'return context.restrictedTraverse(' \
'context.REQUEST["testUpgradeDecision_notifyDelivered_hosting_subscription"])')
@simulate('UpgradeDecision_isUpgradeFinished',
'', 'return 0')
def testUpgradeDecision_notifyDelivered_hosting_subscription(self):
person = self._makePerson(self.new_id)
hosting_subscription = self._makeHostingSubscription(self.new_id)
software_release = self._makeSoftwareRelease(self.new_id)
software_product = self._makeSoftwareProduct(self.new_id)
software_release.setAggregateValue(software_product)
upgrade_decision = self._makeUpgradeDecision()
upgrade_decision.edit(destination_decision_value=person)
upgrade_decision_line = self._makeUpgradeDecisionLine(upgrade_decision)
upgrade_decision_line.setAggregateValueList([software_release,
hosting_subscription])
old_url = hosting_subscription.getUrlString()
notification_message = self.portal.notification_message_module.newContent(
portal_type="Notification Message",
title='Test NM title %s' % self.new_id,
text_content_substitution_mapping_method_id=
"NotificationMessage_getSubstitutionMappingDictFromArgument",
text_content="""${software_product_title}
${hosting_subscription_title}
${old_software_release_url}
${software_release_name}
${software_release_reference}
${new_software_release_url}""",
content_type='text/html',
)
self.portal.REQUEST\
['testUpgradeDecision_notifyDelivered_hosting_subscription'] = \
notification_message.getRelativeUrl()
self.tic()
self.assertEquals(None, upgrade_decision.UpgradeDecision_notifyDelivered())
upgrade_decision.start()
upgrade_decision.stop()
self.tic()
self.assertEquals(None, upgrade_decision.UpgradeDecision_notifyDelivered())
self.tic()
self.assertEquals(upgrade_decision.getSimulationState(), 'delivered')
self.assertEquals(len(upgrade_decision.getFollowUpRelatedValueList()), 1)
event = upgrade_decision.getFollowUpRelatedValue()
self.assertEquals(event.getTitle(),
"Upgrade Processed for %s (%s)" % (hosting_subscription.getTitle(),
software_release.getReference()))
self.assertEqual(event.getTextContent().splitlines(),
[software_product.getTitle(), hosting_subscription.getTitle(),
old_url, software_release.getTitle(), software_release.getReference(),
software_release.getUrlString()])
self.assertEquals(event.getSimulationState(), "delivered")
...@@ -3,6 +3,7 @@ portal_alarms/slapos_pdm_computer_create_upgrade_decision ...@@ -3,6 +3,7 @@ portal_alarms/slapos_pdm_computer_create_upgrade_decision
portal_alarms/slapos_pdm_hosting_subscription_create_upgrade_decision portal_alarms/slapos_pdm_hosting_subscription_create_upgrade_decision
portal_alarms/slapos_pdm_upgrade_decision_process_planned portal_alarms/slapos_pdm_upgrade_decision_process_planned
portal_alarms/slapos_pdm_upgrade_decision_process_started portal_alarms/slapos_pdm_upgrade_decision_process_started
portal_alarms/slapos_pdm_upgrade_decision_process_stopped
software_product_module/template_software_product software_product_module/template_software_product
software_release_module/template_software_release software_release_module/template_software_release
upgrade_decision_module/template_upgrade_decision upgrade_decision_module/template_upgrade_decision
\ No newline at end of file
...@@ -51,8 +51,8 @@ ...@@ -51,8 +51,8 @@
<item> <item>
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>portal = context.getPortalObject()\n <value> <string>portal = context.getPortalObject()\n
kw[\'portal_type\'] = ["Support Request", "Regularisation Request"]\n kw[\'portal_type\'] = ["Support Request", "Regularisation Request", "Upgrader Decision"]\n
kw[\'simulation_state\'] = [\'validated\',\'submitted\']\n \n
\n \n
person = portal.ERP5Site_getAuthenticatedMemberPersonValue()\n person = portal.ERP5Site_getAuthenticatedMemberPersonValue()\n
if person:\n if person:\n
......
...@@ -57,6 +57,9 @@ import json\n ...@@ -57,6 +57,9 @@ import json\n
portal = context.getPortalObject()\n portal = context.getPortalObject()\n
person = portal.ERP5Site_getAuthenticatedMemberPersonValue()\n person = portal.ERP5Site_getAuthenticatedMemberPersonValue()\n
\n \n
if person is None:\n
raise ValueError("User Not Found")\n
\n
web_site = context.getWebSiteValue()\n web_site = context.getWebSiteValue()\n
request_url = "%s/%s" % (web_site.absolute_url(), "feed")\n request_url = "%s/%s" % (web_site.absolute_url(), "feed")\n
\n \n
...@@ -69,22 +72,24 @@ for token_item in portal.portal_catalog(\n ...@@ -69,22 +72,24 @@ for token_item in portal.portal_catalog(\n
):\n ):\n
if token_item.getUrlString() == request_url:\n if token_item.getUrlString() == request_url:\n
access_token = token_item\n access_token = token_item\n
reference = access_token.getReference()\n
break;\n break;\n
\n \n
if access_token is None:\n if access_token is None:\n
access_token = portal.access_token_module.newContent(\n access_token = portal.access_token_module.newContent(\n
portal_type="Restricted Access Token",\n portal_type="Restricted Access Token",\n
agent_value=person,\n
url_string=request_url,\n url_string=request_url,\n
url_method="GET",\n url_method="GET",\n
)\n )\n
access_token.setAgentValue(person)\n
reference = access_token.getReference() \n
access_token.validate()\n access_token.validate()\n
\n \n
url = "%s/%s?portal_skin=RSS&access_token=%s&access_token_secret=%s" % (\n url = "%s/%s?portal_skin=RSS&access_token=%s&access_token_secret=%s" % (\n
web_site.absolute_url(),\n web_site.absolute_url(),\n
"feed",\n "feed",\n
access_token.getId(),\n access_token.getId(),\n
access_token.getReference())\n reference)\n
\n \n
request = context.REQUEST\n request = context.REQUEST\n
response = request.RESPONSE\n response = request.RESPONSE\n
......
...@@ -79,7 +79,7 @@ def do_collect(conf): ...@@ -79,7 +79,7 @@ def do_collect(conf):
raise raise
log_directory = "%s/var/data-log" % conf.get("slapos", "instance_root") log_directory = "%s/var/data-log" % conf.get("slapos", "instance_root")
mkdir_p(log_directory) mkdir_p(log_directory, 0o755)
database = Database(log_directory) database = Database(log_directory)
computer = Computer(ComputerSnapshot()) computer = Computer(ComputerSnapshot())
......
...@@ -37,6 +37,7 @@ import subprocess ...@@ -37,6 +37,7 @@ import subprocess
import sys import sys
import tempfile import tempfile
import time import time
import stat
import traceback import traceback
import warnings import warnings
import logging import logging
...@@ -352,8 +353,17 @@ class Slapgrid(object): ...@@ -352,8 +353,17 @@ class Slapgrid(object):
raise OSError('%s does not exist.' % self.instance_root) raise OSError('%s does not exist.' % self.instance_root)
# Creates everything needed # Creates everything needed
# Create directory accessible for the instances.
var_directory = os.path.join(self.instance_root, 'var')
if not os.path.isdir(var_directory):
os.mkdir(var_directory)
os.chmod(var_directory, stat.S_IRWXU | stat.S_IROTH | stat.S_IXOTH | \
stat.S_IRGRP | stat.S_IXGRP )
mkdir_p(os.path.join(self.instance_root, 'var'), 0o755)
# Creates instance_root structure # Creates instance_root structure
createPrivateDirectory(os.path.join(self.instance_root, 'var'))
createPrivateDirectory(os.path.join(self.instance_root, 'var', 'log')) createPrivateDirectory(os.path.join(self.instance_root, 'var', 'log'))
createPrivateDirectory(os.path.join(self.instance_root, 'var', 'run')) createPrivateDirectory(os.path.join(self.instance_root, 'var', 'run'))
......
--version:10 --version:11
CREATE TABLE IF NOT EXISTS software%(version)s (url VARCHAR(255) UNIQUE); CREATE TABLE IF NOT EXISTS software%(version)s (
url VARCHAR(255),
computer_reference VARCHAR(255) DEFAULT '%(computer)s',
CONSTRAINT uniq PRIMARY KEY (url, computer_reference)
);
CREATE TABLE IF NOT EXISTS computer%(version)s ( CREATE TABLE IF NOT EXISTS computer%(version)s (
reference VARCHAR(255) DEFAULT '%(computer)s',
address VARCHAR(255), address VARCHAR(255),
netmask VARCHAR(255), netmask VARCHAR(255),
CONSTRAINT uniq PRIMARY KEY (address, netmask)); CONSTRAINT uniq PRIMARY KEY (reference)
);
CREATE TABLE IF NOT EXISTS partition%(version)s ( CREATE TABLE IF NOT EXISTS partition%(version)s (
reference VARCHAR(255) UNIQUE, reference VARCHAR(255),
computer_reference VARCHAR(255) DEFAULT '%(computer)s',
slap_state VARCHAR(255) DEFAULT 'free', slap_state VARCHAR(255) DEFAULT 'free',
software_release VARCHAR(255), software_release VARCHAR(255),
xml TEXT, xml TEXT,
...@@ -16,11 +24,13 @@ CREATE TABLE IF NOT EXISTS partition%(version)s ( ...@@ -16,11 +24,13 @@ CREATE TABLE IF NOT EXISTS partition%(version)s (
partition_reference VARCHAR(255), partition_reference VARCHAR(255),
requested_by VARCHAR(255), -- only used for debugging, requested_by VARCHAR(255), -- only used for debugging,
-- slapproxy does not support proper scope -- slapproxy does not support proper scope
requested_state VARCHAR(255) NOT NULL DEFAULT 'started' requested_state VARCHAR(255) NOT NULL DEFAULT 'started',
CONSTRAINT uniq PRIMARY KEY (reference, computer_reference)
); );
CREATE TABLE IF NOT EXISTS slave%(version)s ( CREATE TABLE IF NOT EXISTS slave%(version)s (
reference VARCHAR(255) UNIQUE, reference VARCHAR(255),
computer_reference VARCHAR(255) DEFAULT '%(computer)s',
connection_xml TEXT, connection_xml TEXT,
hosted_by VARCHAR(255), hosted_by VARCHAR(255),
asked_by VARCHAR(255) -- only used for debugging, asked_by VARCHAR(255) -- only used for debugging,
...@@ -29,7 +39,9 @@ CREATE TABLE IF NOT EXISTS slave%(version)s ( ...@@ -29,7 +39,9 @@ CREATE TABLE IF NOT EXISTS slave%(version)s (
CREATE TABLE IF NOT EXISTS partition_network%(version)s ( CREATE TABLE IF NOT EXISTS partition_network%(version)s (
partition_reference VARCHAR(255), partition_reference VARCHAR(255),
computer_reference VARCHAR(255) DEFAULT '%(computer)s',
reference VARCHAR(255), reference VARCHAR(255),
address VARCHAR(255), address VARCHAR(255),
netmask VARCHAR(255) netmask VARCHAR(255)
); );
...@@ -73,12 +73,15 @@ def dict2xml(dictionary): ...@@ -73,12 +73,15 @@ def dict2xml(dictionary):
def partitiondict2partition(partition): def partitiondict2partition(partition):
slap_partition = ComputerPartition(app.config['computer_id'], for key, value in partition.iteritems():
if type(value) is unicode:
partition[key] = value.encode()
slap_partition = ComputerPartition(partition['computer_reference'],
partition['reference']) partition['reference'])
slap_partition._software_release_document = None slap_partition._software_release_document = None
slap_partition._requested_state = 'destroyed' slap_partition._requested_state = 'destroyed'
slap_partition._need_modification = 0 slap_partition._need_modification = 0
slap_partition._instance_guid = partition['reference'] slap_partition._instance_guid = '%s-%s' % (partition['computer_reference'], partition['reference'])
if partition['software_release']: if partition['software_release']:
slap_partition._need_modification = 1 slap_partition._need_modification = 1
...@@ -86,8 +89,8 @@ def partitiondict2partition(partition): ...@@ -86,8 +89,8 @@ def partitiondict2partition(partition):
slap_partition._parameter_dict = xml2dict(partition['xml']) slap_partition._parameter_dict = xml2dict(partition['xml'])
address_list = [] address_list = []
for address in execute_db('partition_network', for address in execute_db('partition_network',
'SELECT * FROM %s WHERE partition_reference=?', 'SELECT * FROM %s WHERE partition_reference=? AND computer_reference=?',
[partition['reference']]): [partition['reference'], partition['computer_reference']]):
address_list.append((address['reference'], address['address'])) address_list.append((address['reference'], address['address']))
slap_partition._parameter_dict['ip_list'] = address_list slap_partition._parameter_dict['ip_list'] = address_list
slap_partition._parameter_dict['slap_software_type'] = \ slap_partition._parameter_dict['slap_software_type'] = \
...@@ -95,17 +98,24 @@ def partitiondict2partition(partition): ...@@ -95,17 +98,24 @@ def partitiondict2partition(partition):
if partition['slave_instance_list'] is not None: if partition['slave_instance_list'] is not None:
slap_partition._parameter_dict['slave_instance_list'] = \ slap_partition._parameter_dict['slave_instance_list'] = \
xml_marshaller.xml_marshaller.loads(partition['slave_instance_list']) xml_marshaller.xml_marshaller.loads(partition['slave_instance_list'])
else:
slap_partition._parameter_dict['slave_instance_list'] = []
slap_partition._connection_dict = xml2dict(partition['connection_xml']) slap_partition._connection_dict = xml2dict(partition['connection_xml'])
slap_partition._software_release_document = SoftwareRelease( slap_partition._software_release_document = SoftwareRelease(
software_release=partition['software_release'], software_release=partition['software_release'],
computer_guid=app.config['computer_id']) computer_guid=partition['computer_reference'])
return slap_partition return slap_partition
def execute_db(table, query, args=(), one=False): def execute_db(table, query, args=(), one=False, db_version=None, log=False):
if not db_version:
db_version = DB_VERSION
query = query % (table + db_version,)
if log:
print query
try: try:
cur = g.db.execute(query % (table + DB_VERSION,), args) cur = g.db.execute(query, args)
except: except:
app.logger.error('There was some issue during processing query %r on table %r with args %r' % (query, table, args)) app.logger.error('There was some issue during processing query %r on table %r with args %r' % (query, table, args))
raise raise
...@@ -117,15 +127,66 @@ def execute_db(table, query, args=(), one=False): ...@@ -117,15 +127,66 @@ def execute_db(table, query, args=(), one=False):
def connect_db(): def connect_db():
return sqlite3.connect(app.config['DATABASE_URI']) return sqlite3.connect(app.config['DATABASE_URI'])
def _getTableList():
return g.db.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY Name").fetchall()
def _getCurrentDatabaseSchemaVersion():
"""
Return version of database schema.
As there is no actual definition of version, analyse
name of all tables (containing version) and take the
highest version (as several versions can live in the db).
"""
# XXX: define an actual version and proper migration/repair procedure.
version = -1
for table_name in _getTableList():
try:
table_version = int(table_name[0][-2:])
except ValueError:
table_version = int(table_name[0][-1:])
if table_version > version:
version = table_version
return str(version)
def _upgradeDatabaseIfNeeded():
"""
Analyses current database compared to defined schema,
and adapt tables/data it if needed.
"""
current_schema_version = _getCurrentDatabaseSchemaVersion()
# If version of current database is not old, do nothing
if current_schema_version == DB_VERSION:
return
@app.before_request
def before_request():
g.db = connect_db()
schema = app.open_resource('schema.sql') schema = app.open_resource('schema.sql')
schema = schema.read() % dict(version=DB_VERSION) schema = schema.read() % dict(version=DB_VERSION, computer=app.config['computer_id'])
g.db.cursor().executescript(schema) g.db.cursor().executescript(schema)
g.db.commit() g.db.commit()
if current_schema_version == '-1':
return
# Migrate all data to new tables
app.logger.info('Old schema detected: Migrating old tables...')
app.logger.info('Note that old tables are not alterated.')
for table in ('software', 'computer', 'partition', 'slave', 'partition_network'):
for row in execute_db(table, 'SELECT * from %s', db_version=current_schema_version):
columns = ', '.join(row.keys())
placeholders = ':'+', :'.join(row.keys())
query = 'INSERT INTO %s (%s) VALUES (%s)' % ('%s', columns, placeholders)
execute_db(table, query, row, log=True)
g.db.commit()
is_schema_already_executed = False
@app.before_request
def before_request():
g.db = connect_db()
global is_schema_already_executed
if not is_schema_already_executed:
_upgradeDatabaseIfNeeded()
is_schema_already_executed = True
@app.after_request @app.after_request
def after_request(response): def after_request(response):
...@@ -141,37 +202,39 @@ def getComputerInformation(): ...@@ -141,37 +202,39 @@ def getComputerInformation():
@app.route('/getFullComputerInformation', methods=['GET']) @app.route('/getFullComputerInformation', methods=['GET'])
def getFullComputerInformation(): def getFullComputerInformation():
computer_id = request.args['computer_id'] computer_id = request.args['computer_id']
if app.config['computer_id'] == computer_id: computer_list = execute_db('computer', 'SELECT * FROM %s WHERE reference=?', [computer_id])
if len(computer_list) != 1:
# Backward compatibility
if computer_id != app.config['computer_id']:
raise NotFoundError('%s is not registered.' % computer_id)
slap_computer = Computer(computer_id) slap_computer = Computer(computer_id)
slap_computer._software_release_list = [] slap_computer._software_release_list = []
for sr in execute_db('software', 'select * from %s'): for sr in execute_db('software', 'select * from %s WHERE computer_reference=?', [computer_id]):
slap_computer._software_release_list.append(SoftwareRelease( slap_computer._software_release_list.append(SoftwareRelease(
software_release=sr['url'], computer_guid=computer_id)) software_release=sr['url'], computer_guid=computer_id))
slap_computer._computer_partition_list = [] slap_computer._computer_partition_list = []
for partition in execute_db('partition', 'SELECT * FROM %s'): for partition in execute_db('partition', 'SELECT * FROM %s WHERE computer_reference=?', [computer_id]):
slap_computer._computer_partition_list.append(partitiondict2partition( slap_computer._computer_partition_list.append(partitiondict2partition(
partition)) partition))
return xml_marshaller.xml_marshaller.dumps(slap_computer) return xml_marshaller.xml_marshaller.dumps(slap_computer)
else:
raise NotFoundError('Only accept request for: %s' % app.config['computer_id'])
@app.route('/setComputerPartitionConnectionXml', methods=['POST']) @app.route('/setComputerPartitionConnectionXml', methods=['POST'])
def setComputerPartitionConnectionXml(): def setComputerPartitionConnectionXml():
slave_reference = request.form['slave_reference'].encode() slave_reference = request.form['slave_reference'].encode()
computer_partition_id = request.form['computer_partition_id'] computer_partition_id = request.form['computer_partition_id'].encode()
connection_xml = request.form['connection_xml'] computer_id = request.form['computer_id'].encode()
connection_xml = request.form['connection_xml'].encode()
connection_dict = xml_marshaller.xml_marshaller.loads( connection_dict = xml_marshaller.xml_marshaller.loads(
connection_xml.encode()) connection_xml)
connection_xml = dict2xml(connection_dict) connection_xml = dict2xml(connection_dict)
if slave_reference == 'None': if slave_reference == 'None':
query = 'UPDATE %s SET connection_xml=? WHERE reference=?' query = 'UPDATE %s SET connection_xml=? WHERE reference=? AND computer_reference=?'
argument_list = [connection_xml, computer_partition_id.encode()] argument_list = [connection_xml, computer_partition_id, computer_id]
execute_db('partition', query, argument_list) execute_db('partition', query, argument_list)
return 'done' return 'done'
else: else:
query = 'UPDATE %s SET connection_xml=? , hosted_by=? WHERE reference=?' query = 'UPDATE %s SET connection_xml=? , hosted_by=? WHERE reference=?'
argument_list = [connection_xml, computer_partition_id.encode(), argument_list = [connection_xml, computer_partition_id, slave_reference]
slave_reference]
execute_db('slave', query, argument_list) execute_db('slave', query, argument_list)
return 'done' return 'done'
...@@ -223,47 +286,41 @@ def useComputer(): ...@@ -223,47 +286,41 @@ def useComputer():
def loadComputerConfigurationFromXML(): def loadComputerConfigurationFromXML():
xml = request.form['xml'] xml = request.form['xml']
computer_dict = xml_marshaller.xml_marshaller.loads(str(xml)) computer_dict = xml_marshaller.xml_marshaller.loads(str(xml))
if app.config['computer_id'] == computer_dict['reference']: execute_db('computer', 'INSERT OR REPLACE INTO %s values(:reference, :address, :netmask)',
execute_db('computer', 'INSERT OR REPLACE INTO %s values(:address, :netmask)',
computer_dict) computer_dict)
for partition in computer_dict['partition_list']: for partition in computer_dict['partition_list']:
partition['computer_reference'] = computer_dict['reference']
execute_db('partition', 'INSERT OR IGNORE INTO %s (reference) values(:reference)', partition) execute_db('partition', 'INSERT OR IGNORE INTO %s (reference, computer_reference) values(:reference, :computer_reference)', partition)
execute_db('partition_network', 'DELETE FROM %s WHERE partition_reference = ?', [partition['reference']]) execute_db('partition_network', 'DELETE FROM %s WHERE partition_reference = ? AND computer_reference = ?',
[partition['reference'], partition['computer_reference']])
for address in partition['address_list']: for address in partition['address_list']:
address['reference'] = partition['tap']['name'] address['reference'] = partition['tap']['name']
address['partition_reference'] = partition['reference'] address['partition_reference'] = partition['reference']
execute_db('partition_network', 'INSERT OR REPLACE INTO %s (reference, partition_reference, address, netmask) values(:reference, :partition_reference, :addr, :netmask)', address) address['computer_reference'] = partition['computer_reference']
execute_db('partition_network', 'INSERT OR REPLACE INTO %s (reference, partition_reference, computer_reference, address, netmask) values(:reference, :partition_reference, :computer_reference, :addr, :netmask)', address)
return 'done' return 'done'
else:
raise UnauthorizedError('Only accept request for: %s' % app.config['computer_id'])
@app.route('/registerComputerPartition', methods=['GET']) @app.route('/registerComputerPartition', methods=['GET'])
def registerComputerPartition(): def registerComputerPartition():
computer_reference = request.args['computer_reference'] computer_reference = request.args['computer_reference'].encode()
computer_partition_reference = request.args['computer_partition_reference'] computer_partition_reference = request.args['computer_partition_reference'].encode()
if app.config['computer_id'] == computer_reference: partition = execute_db('partition', 'SELECT * FROM %s WHERE reference=? and computer_reference=?',
partition = execute_db('partition', 'SELECT * FROM %s WHERE reference=?', [computer_partition_reference, computer_reference], one=True)
[computer_partition_reference.encode()], one=True)
if partition is None: if partition is None:
raise UnauthorizedError raise UnauthorizedError
return xml_marshaller.xml_marshaller.dumps( return xml_marshaller.xml_marshaller.dumps(
partitiondict2partition(partition)) partitiondict2partition(partition))
else:
raise UnauthorizedError('Only accept request for: %s' % app.config['computer_id'])
@app.route('/supplySupply', methods=['POST']) @app.route('/supplySupply', methods=['POST'])
def supplySupply(): def supplySupply():
url = request.form['url'] url = request.form['url']
computer_id = request.form['computer_id'] computer_id = request.form['computer_id']
if app.config['computer_id'] == computer_id:
if request.form['state'] == 'destroyed': if request.form['state'] == 'destroyed':
execute_db('software', 'DELETE FROM %s WHERE url = ?', [url]) execute_db('software', 'DELETE FROM %s WHERE url = ? AND computer_reference=?',
else: [url, computer_id])
execute_db('software', 'INSERT OR REPLACE INTO %s VALUES(?)', [url])
else: else:
raise UnauthorizedError('Only accept request for: %s' % app.config['computer_id']) execute_db('software', 'INSERT OR REPLACE INTO %s VALUES(?, ?)', [url, computer_id])
return '%r added' % url return '%r added' % url
...@@ -281,17 +338,22 @@ def requestComputerPartition(): ...@@ -281,17 +338,22 @@ def requestComputerPartition():
def softwareInstanceRename(): def softwareInstanceRename():
new_name = request.form['new_name'].encode() new_name = request.form['new_name'].encode()
computer_partition_id = request.form['computer_partition_id'].encode() computer_partition_id = request.form['computer_partition_id'].encode()
computer_id = request.form['computer_id'].encode()
q = 'UPDATE %s SET partition_reference = ? WHERE reference = ?' q = 'UPDATE %s SET partition_reference = ? WHERE reference = ? AND computer_reference = ?'
execute_db('partition', q, [new_name, computer_partition_id]) execute_db('partition', q, [new_name, computer_partition_id, computer_id])
return 'done' return 'done'
@app.route('/getComputerPartitionStatus', methods=['GET'])
def getComputerPartitionStatus():
return xml_marshaller.xml_marshaller.dumps('Not implemented.')
def request_not_shared(): def request_not_shared():
software_release = request.form['software_release'].encode() software_release = request.form['software_release'].encode()
# some supported parameters # some supported parameters
software_type = request.form.get('software_type').encode() software_type = request.form.get('software_type').encode()
partition_reference = request.form.get('partition_reference', '').encode() partition_reference = request.form.get('partition_reference', '').encode()
filter_kw = request.form.get('filter_xml', None)
partition_id = request.form.get('computer_partition_id', '').encode() partition_id = request.form.get('computer_partition_id', '').encode()
partition_parameter_kw = request.form.get('partition_parameter_xml', None) partition_parameter_kw = request.form.get('partition_parameter_xml', None)
requested_state = xml_marshaller.xml_marshaller.loads(request.form.get('state').encode()) requested_state = xml_marshaller.xml_marshaller.loads(request.form.get('state').encode())
...@@ -300,6 +362,11 @@ def request_not_shared(): ...@@ -300,6 +362,11 @@ def request_not_shared():
partition_parameter_kw.encode()) partition_parameter_kw.encode())
else: else:
partition_parameter_kw = {} partition_parameter_kw = {}
if filter_kw:
filter_kw = xml_marshaller.xml_marshaller.loads(filter_kw.encode())
requested_computer_id = filter_kw.get('computer_guid', app.config['computer_id'])
else:
requested_computer_id = app.config['computer_id']
instance_xml = dict2xml(partition_parameter_kw) instance_xml = dict2xml(partition_parameter_kw)
args = [] args = []
...@@ -318,9 +385,12 @@ def request_not_shared(): ...@@ -318,9 +385,12 @@ def request_not_shared():
a(requested_state) a(requested_state)
# If partition doesn't exist: create it and insert parameters # If partition doesn't exist: create it and insert parameters
# XXX add support for automatic deployment on specific node depending on available SR and partitions on each Node.
# Note: only deploy on default node if SLA not specified
if partition is None: if partition is None:
partition = execute_db('partition', partition = execute_db('partition',
'SELECT * FROM %s WHERE slap_state="free"', (), one=True) 'SELECT * FROM %s WHERE slap_state="free" and computer_reference=?',
[requested_computer_id], one=True)
if partition is None: if partition is None:
app.logger.warning('No more free computer partition') app.logger.warning('No more free computer partition')
abort(404) abort(404)
...@@ -346,30 +416,32 @@ def request_not_shared(): ...@@ -346,30 +416,32 @@ def request_not_shared():
if instance_xml: if instance_xml:
q += ' ,xml=?' q += ' ,xml=?'
a(instance_xml) a(instance_xml)
q += ' WHERE reference=?' q += ' WHERE reference=? AND computer_reference=?'
a(partition['reference'].encode()) a(partition['reference'].encode())
a(partition['computer_reference'].encode())
execute_db('partition', q, args) execute_db('partition', q, args)
args = [] args = []
partition = execute_db('partition', 'SELECT * FROM %s WHERE reference=?', partition = execute_db('partition', 'SELECT * FROM %s WHERE reference=? and computer_reference=?',
[partition['reference'].encode()], one=True) [partition['reference'].encode(), partition['computer_reference'].encode()], one=True)
address_list = [] address_list = []
for address in execute_db('partition_network', 'SELECT * FROM %s WHERE partition_reference=?', [partition['reference']]): for address in execute_db('partition_network', 'SELECT * FROM %s WHERE partition_reference=?', [partition['reference']]):
address_list.append((address['reference'], address['address'])) address_list.append((address['reference'], address['address']))
if not requested_state:
requested_state = 'started'
# XXX it should be ComputerPartition, not a SoftwareInstance # XXX it should be ComputerPartition, not a SoftwareInstance
software_instance = SoftwareInstance(xml=partition['xml'], software_instance = SoftwareInstance(_connection_dict=xml2dict(partition['connection_xml']),
_connection_dict=xml2dict(partition['connection_xml']),
_parameter_dict=xml2dict(partition['xml']), _parameter_dict=xml2dict(partition['xml']),
connection_xml=partition['connection_xml'], connection_xml=partition['connection_xml'],
slap_computer_id=app.config['computer_id'], slap_computer_id=partition['computer_reference'].encode(),
slap_computer_partition_id=partition['reference'], slap_computer_partition_id=partition['reference'],
slap_software_release_url=partition['software_release'], slap_software_release_url=partition['software_release'],
slap_server_url='slap_server_url', slap_server_url='slap_server_url',
slap_software_type=partition['software_type'], slap_software_type=partition['software_type'],
slave_instance_list=partition['slave_instance_list'], _instance_guid='%s-%s' % (partition['computer_reference'].encode(), partition['reference']),
instance_guid=partition['reference'], _requested_state=requested_state,
ip_list=address_list) ip_list=address_list)
return xml_marshaller.xml_marshaller.dumps(software_instance) return xml_marshaller.xml_marshaller.dumps(software_instance)
...@@ -397,14 +469,20 @@ def request_slave(): ...@@ -397,14 +469,20 @@ def request_slave():
else: else:
partition_parameter_kw = {} partition_parameter_kw = {}
filter_kw = xml_marshaller.xml_marshaller.loads(request.form.get('filter_xml').encode()) filter_kw = request.form.get('filter_xml', None)
if filter_kw:
filter_kw = xml_marshaller.xml_marshaller.loads(filter_kw.encode())
requested_computer_id = filter_kw.get('computer_guid', app.config['computer_id'])
else:
requested_computer_id = app.config['computer_id']
instance_xml = dict2xml(partition_parameter_kw) instance_xml = dict2xml(partition_parameter_kw)
# We will search for a master corresponding to request # We will search for a master corresponding to request
args = [] args = []
a = args.append a = args.append
q = 'SELECT * FROM %s WHERE software_release=?' q = 'SELECT * FROM %s WHERE software_release=? and computer_reference=?'
a(software_release) a(software_release)
a(requested_computer_id)
if software_type: if software_type:
q += ' AND software_type=?' q += ' AND software_type=?'
a(software_type) a(software_type)
...@@ -433,7 +511,7 @@ def request_slave(): ...@@ -433,7 +511,7 @@ def request_slave():
if slave_instance_list is None: if slave_instance_list is None:
slave_instance_list = [] slave_instance_list = []
else: else:
slave_instance_list = xml_marshaller.xml_marshaller.loads(slave_instance_list) slave_instance_list = xml_marshaller.xml_marshaller.loads(slave_instance_list.encode())
for x in slave_instance_list: for x in slave_instance_list:
if x['slave_reference'] == slave_reference: if x['slave_reference'] == slave_reference:
slave_instance_list.remove(x) slave_instance_list.remove(x)
...@@ -445,33 +523,34 @@ def request_slave(): ...@@ -445,33 +523,34 @@ def request_slave():
a = args.append a = args.append
q = 'UPDATE %s SET slave_instance_list=?' q = 'UPDATE %s SET slave_instance_list=?'
a(xml_marshaller.xml_marshaller.dumps(slave_instance_list)) a(xml_marshaller.xml_marshaller.dumps(slave_instance_list))
q += ' WHERE reference=?' q += ' WHERE reference=? and computer_reference=?'
a(partition['reference'].encode()) a(partition['reference'].encode())
a(requested_computer_id)
execute_db('partition', q, args) execute_db('partition', q, args)
args = [] args = []
partition = execute_db('partition', 'SELECT * FROM %s WHERE reference=?', partition = execute_db('partition', 'SELECT * FROM %s WHERE reference=? and computer_reference=?',
[partition['reference'].encode()], one=True) [partition['reference'].encode(), requested_computer_id], one=True)
# Add slave to slave table if not there # Add slave to slave table if not there
slave = execute_db('slave', 'SELECT * FROM %s WHERE reference=?', slave = execute_db('slave', 'SELECT * FROM %s WHERE reference=? and computer_reference=?',
[slave_reference], one=True) [slave_reference, requested_computer_id], one=True)
if slave is None: if slave is None:
execute_db('slave', execute_db('slave',
'INSERT OR IGNORE INTO %s (reference,asked_by,hosted_by) values(:reference,:asked_by,:hosted_by)', 'INSERT OR IGNORE INTO %s (reference,computer_reference,asked_by,hosted_by) values(:reference,:computer_reference,:asked_by,:hosted_by)',
[slave_reference, partition_id, partition['reference']]) [slave_reference, requested_computer_id, partition_id, partition['reference']])
slave = execute_db('slave', 'SELECT * FROM %s WHERE reference=?', slave = execute_db('slave', 'SELECT * FROM %s WHERE reference=? and computer_reference=?',
[slave_reference], one=True) [slave_reference, requested_computer_id], one=True)
address_list = [] address_list = []
for address in execute_db('partition_network', for address in execute_db('partition_network',
'SELECT * FROM %s WHERE partition_reference=?', 'SELECT * FROM %s WHERE partition_reference=? and computer_reference=?',
[partition['reference']]): [partition['reference'], partition['computer_reference']]):
address_list.append((address['reference'], address['address'])) address_list.append((address['reference'], address['address']))
# XXX it should be ComputerPartition, not a SoftwareInstance # XXX it should be ComputerPartition, not a SoftwareInstance
software_instance = SoftwareInstance(_connection_dict=xml2dict(slave['connection_xml']), software_instance = SoftwareInstance(_connection_dict=xml2dict(slave['connection_xml']),
xml=instance_xml, _parameter_dict=xml2dict(instance_xml),
slap_computer_id=app.config['computer_id'], slap_computer_id=partition['computer_reference'],
slap_computer_partition_id=slave['hosted_by'], slap_computer_partition_id=slave['hosted_by'],
slap_software_release_url=partition['software_release'], slap_software_release_url=partition['software_release'],
slap_server_url='slap_server_url', slap_server_url='slap_server_url',
...@@ -495,5 +574,6 @@ def getSoftwareReleaseListFromSoftwareProduct(): ...@@ -495,5 +574,6 @@ def getSoftwareReleaseListFromSoftwareProduct():
software_release_url_list =\ software_release_url_list =\
[app.config['software_product_list'][software_product_reference]] [app.config['software_product_list'][software_product_reference]]
else: else:
software_release_url_list =[] software_release_url_list = []
return xml_marshaller.xml_marshaller.dumps(software_release_url_list) return xml_marshaller.xml_marshaller.dumps(software_release_url_list)
...@@ -34,6 +34,7 @@ import shutil ...@@ -34,6 +34,7 @@ import shutil
import signal import signal
import socket import socket
import sys import sys
import stat
import tempfile import tempfile
import textwrap import textwrap
import time import time
...@@ -535,6 +536,8 @@ class TestSlapgridCPWithMaster(MasterMixin, unittest.TestCase): ...@@ -535,6 +536,8 @@ class TestSlapgridCPWithMaster(MasterMixin, unittest.TestCase):
self.assertEqual(self.grid.processComputerPartitionList(), slapgrid.SLAPGRID_SUCCESS) self.assertEqual(self.grid.processComputerPartitionList(), slapgrid.SLAPGRID_SUCCESS)
self.assertItemsEqual(os.listdir(self.instance_root), ['etc', 'var']) self.assertItemsEqual(os.listdir(self.instance_root), ['etc', 'var'])
self.assertItemsEqual(os.listdir(self.software_root), []) self.assertItemsEqual(os.listdir(self.software_root), [])
st = os.stat(os.path.join(self.instance_root, 'var'))
self.assertEquals(stat.S_IMODE(st.st_mode), 0o755)
def test_one_partition(self): def test_one_partition(self):
computer = ComputerForTest(self.software_root, self.instance_root) computer = ComputerForTest(self.software_root, self.instance_root)
......
...@@ -34,11 +34,15 @@ import shutil ...@@ -34,11 +34,15 @@ import shutil
import tempfile import tempfile
import unittest import unittest
import xml_marshaller import xml_marshaller
from xml_marshaller.xml_marshaller import loads, dumps
import slapos.proxy import slapos.proxy
import slapos.proxy.views as views import slapos.proxy.views as views
import slapos.slap.slap import slapos.slap.slap
import sqlite3
import pkg_resources
class WrongFormat(Exception): class WrongFormat(Exception):
pass pass
...@@ -104,13 +108,15 @@ database_uri = %(tempdir)s/lib/proxy.db ...@@ -104,13 +108,15 @@ database_uri = %(tempdir)s/lib/proxy.db
self.app_config = views.app.config self.app_config = views.app.config
self.app = views.app.test_client() self.app = views.app.test_client()
def add_free_partition(self, partition_amount): def add_free_partition(self, partition_amount, computer_id=None):
""" """
Will simulate a slapformat first run Will simulate a slapformat first run
and create "partition_amount" partitions and create "partition_amount" partitions
""" """
if not computer_id:
computer_id = self.computer_id
computer_dict = { computer_dict = {
'reference': self.computer_id, 'reference': computer_id,
'address': '123.456.789', 'address': '123.456.789',
'netmask': 'fffffffff', 'netmask': 'fffffffff',
'partition_list': [], 'partition_list': [],
...@@ -118,7 +124,11 @@ database_uri = %(tempdir)s/lib/proxy.db ...@@ -118,7 +124,11 @@ database_uri = %(tempdir)s/lib/proxy.db
for i in range(partition_amount): for i in range(partition_amount):
partition_example = { partition_example = {
'reference': 'slappart%s' % i, 'reference': 'slappart%s' % i,
'address_list': [], 'address_list': [
{'addr': '1.2.3.4', 'netmask': '255.255.255.255'},
{'addr': '4.3.2.1', 'netmask': '255.255.255.255'}
],
'tap': {'name': 'tap0'},
} }
computer_dict['partition_list'].append(partition_example) computer_dict['partition_list'].append(partition_example)
...@@ -126,14 +136,16 @@ database_uri = %(tempdir)s/lib/proxy.db ...@@ -126,14 +136,16 @@ database_uri = %(tempdir)s/lib/proxy.db
'computer_id': self.computer_id, 'computer_id': self.computer_id,
'xml': xml_marshaller.xml_marshaller.dumps(computer_dict), 'xml': xml_marshaller.xml_marshaller.dumps(computer_dict),
} }
self.app.post('/loadComputerConfigurationFromXML', rv = self.app.post('/loadComputerConfigurationFromXML',
data=request_dict) data=request_dict)
self.assertEqual(rv._status_code, 200)
def tearDown(self): def tearDown(self):
""" """
Remove files generated for test Remove files generated for test
""" """
shutil.rmtree(self._tempdir, True) shutil.rmtree(self._tempdir, True)
views.is_schema_already_executed = False
class TestInformation(BasicMixin, unittest.TestCase): class TestInformation(BasicMixin, unittest.TestCase):
...@@ -243,18 +255,16 @@ class TestInformation(BasicMixin, unittest.TestCase): ...@@ -243,18 +255,16 @@ class TestInformation(BasicMixin, unittest.TestCase):
) )
class MasterMixin(BasicMixin): class MasterMixin(BasicMixin, unittest.TestCase):
""" """
Define advanced tool for test proxy simulating behavior slap library tools Define advanced tool for test proxy simulating behavior slap library tools
""" """
def _requestComputerPartition(self, software_release, software_type, partition_reference,
def request(self, software_release, software_type, partition_reference,
partition_id, partition_id,
shared=False, partition_parameter_kw=None, filter_kw=None, shared=False, partition_parameter_kw=None, filter_kw=None,
state=None): state=None):
""" """
Simulate a request with above parameters Check parameters, call requestComputerPartition server method and return result
Return response by server (a computer partition or an error)
""" """
if partition_parameter_kw is None: if partition_parameter_kw is None:
partition_parameter_kw = {} partition_parameter_kw = {}
...@@ -276,25 +286,33 @@ class MasterMixin(BasicMixin): ...@@ -276,25 +286,33 @@ class MasterMixin(BasicMixin):
'filter_xml': xml_marshaller.xml_marshaller.dumps(filter_kw), 'filter_xml': xml_marshaller.xml_marshaller.dumps(filter_kw),
'state': xml_marshaller.xml_marshaller.dumps(state), 'state': xml_marshaller.xml_marshaller.dumps(state),
} }
rv = self.app.post('/requestComputerPartition', return self.app.post('/requestComputerPartition', data=request_dict)
data=request_dict)
def request(self, *args, **kwargs):
"""
Simulate a request with above parameters
Return response by server (a computer partition or an error)
"""
rv = self._requestComputerPartition(*args, **kwargs)
self.assertEqual(rv._status_code, 200)
xml = rv.data xml = rv.data
try:
software_instance = xml_marshaller.xml_marshaller.loads(xml) software_instance = xml_marshaller.xml_marshaller.loads(xml)
except:
raise WrongFormat("Could not be parsed by xml_marshaller")
computer_partition = slapos.slap.ComputerPartition( computer_partition = slapos.slap.ComputerPartition(
software_instance.slap_computer_id, software_instance.slap_computer_id,
software_instance.slap_computer_partition_id) software_instance.slap_computer_partition_id)
if shared:
computer_partition._synced = True computer_partition.__dict__.update(software_instance.__dict__)
computer_partition._connection_dict = getattr(software_instance,
'_connection_dict', None)
computer_partition._parameter_dict = getattr(software_instance,
'_parameter_dict', None)
return computer_partition return computer_partition
def supply(self, url, computer_id=None, state=''):
if not computer_id:
computer_id = self.computer_id
request_dict = {'url':url, 'computer_id': computer_id, 'state':state}
rv = self.app.post('/supplySupply',
data=request_dict)
# XXX return a Software Release
def setConnectionDict(self, partition_id, def setConnectionDict(self, partition_id,
connection_dict, slave_reference=None): connection_dict, slave_reference=None):
self.app.post('/setComputerPartitionConnectionXml', data={ self.app.post('/setComputerPartitionConnectionXml', data={
...@@ -314,10 +332,20 @@ class MasterMixin(BasicMixin): ...@@ -314,10 +332,20 @@ class MasterMixin(BasicMixin):
return instance return instance
class TestRequest(MasterMixin, unittest.TestCase): class TestRequest(MasterMixin):
""" """
Set of tests for requests Set of tests for requests
""" """
def test_request_consistent_parameters(self):
"""
Check that all different parameters related to requests (like instance_guid, state) are set and consistent
"""
self.add_free_partition(1)
partition = self.request('http://sr//', None, 'MyFirstInstance', 'slappart0')
self.assertEqual(partition.getState(), 'started')
self.assertEqual(partition.getInstanceGuid(), 'computer-slappart0')
def test_two_request_one_partition_free(self): def test_two_request_one_partition_free(self):
""" """
Since slapproxy does not implement scope, providing two partition_id Since slapproxy does not implement scope, providing two partition_id
...@@ -325,10 +353,10 @@ class TestRequest(MasterMixin, unittest.TestCase): ...@@ -325,10 +353,10 @@ class TestRequest(MasterMixin, unittest.TestCase):
""" """
self.add_free_partition(1) self.add_free_partition(1)
self.assertIsInstance(self.request('http://sr//', None, self.assertIsInstance(self.request('http://sr//', None,
'Maria', 'slappart2'), 'MyFirstInstance', 'slappart2'),
slapos.slap.ComputerPartition) slapos.slap.ComputerPartition)
self.assertIsInstance(self.request('http://sr//', None, self.assertIsInstance(self.request('http://sr//', None,
'Maria', 'slappart3'), 'MyFirstInstance', 'slappart3'),
slapos.slap.ComputerPartition) slapos.slap.ComputerPartition)
def test_two_request_two_partition_free(self): def test_two_request_two_partition_free(self):
...@@ -338,10 +366,10 @@ class TestRequest(MasterMixin, unittest.TestCase): ...@@ -338,10 +366,10 @@ class TestRequest(MasterMixin, unittest.TestCase):
""" """
self.add_free_partition(2) self.add_free_partition(2)
self.assertIsInstance(self.request('http://sr//', None, self.assertIsInstance(self.request('http://sr//', None,
'Maria', 'slappart2'), 'MyFirstInstance', 'slappart2'),
slapos.slap.ComputerPartition) slapos.slap.ComputerPartition)
self.assertIsInstance(self.request('http://sr//', None, self.assertIsInstance(self.request('http://sr//', None,
'Maria', 'slappart3'), 'MyFirstInstance', 'slappart3'),
slapos.slap.ComputerPartition) slapos.slap.ComputerPartition)
def test_two_same_request_from_one_partition(self): def test_two_same_request_from_one_partition(self):
...@@ -350,8 +378,8 @@ class TestRequest(MasterMixin, unittest.TestCase): ...@@ -350,8 +378,8 @@ class TestRequest(MasterMixin, unittest.TestCase):
""" """
self.add_free_partition(2) self.add_free_partition(2)
self.assertEqual( self.assertEqual(
self.request('http://sr//', None, 'Maria', 'slappart2').__dict__, self.request('http://sr//', None, 'MyFirstInstance', 'slappart2').__dict__,
self.request('http://sr//', None, 'Maria', 'slappart2').__dict__) self.request('http://sr//', None, 'MyFirstInstance', 'slappart2').__dict__)
def test_two_requests_with_different_parameters_but_same_reference(self): def test_two_requests_with_different_parameters_but_same_reference(self):
""" """
...@@ -362,18 +390,18 @@ class TestRequest(MasterMixin, unittest.TestCase): ...@@ -362,18 +390,18 @@ class TestRequest(MasterMixin, unittest.TestCase):
wanted_domain1 = 'fou.org' wanted_domain1 = 'fou.org'
wanted_domain2 = 'carzy.org' wanted_domain2 = 'carzy.org'
request1 = self.request('http://sr//', None, 'Maria', 'slappart2', request1 = self.request('http://sr//', None, 'MyFirstInstance', 'slappart2',
partition_parameter_kw={'domain': wanted_domain1}) partition_parameter_kw={'domain': wanted_domain1})
request1_dict = request1.__dict__ request1_dict = request1.__dict__
requested_result1 = self.getPartitionInformation( requested_result1 = self.getPartitionInformation(
request1_dict['_partition_id']) request1_dict['_partition_id'])
request2 = self.request('http://sr1//', 'Papa', 'Maria', 'slappart2', request2 = self.request('http://sr1//', 'Papa', 'MyFirstInstance', 'slappart2',
partition_parameter_kw={'domain': wanted_domain2}) partition_parameter_kw={'domain': wanted_domain2})
request2_dict = request2.__dict__ request2_dict = request2.__dict__
requested_result2 = self.getPartitionInformation( requested_result2 = self.getPartitionInformation(
request2_dict['_partition_id']) request2_dict['_partition_id'])
# Test we received same partition # Test we received same partition
for key in request1_dict: for key in ['_partition_id', '_computer_id']:
self.assertEqual(request1_dict[key], request2_dict[key]) self.assertEqual(request1_dict[key], request2_dict[key])
# Test that only parameters changed # Test that only parameters changed
for key in requested_result2.__dict__: for key in requested_result2.__dict__:
...@@ -397,8 +425,8 @@ class TestRequest(MasterMixin, unittest.TestCase): ...@@ -397,8 +425,8 @@ class TestRequest(MasterMixin, unittest.TestCase):
""" """
self.add_free_partition(2) self.add_free_partition(2)
self.assertEqual( self.assertEqual(
self.request('http://sr//', None, 'Maria', 'slappart2').__dict__, self.request('http://sr//', None, 'MyFirstInstance', 'slappart2').__dict__,
self.request('http://sr//', None, 'Maria', 'slappart3').__dict__) self.request('http://sr//', None, 'MyFirstInstance', 'slappart3').__dict__)
def test_two_different_request_from_one_partition(self): def test_two_different_request_from_one_partition(self):
""" """
...@@ -407,16 +435,21 @@ class TestRequest(MasterMixin, unittest.TestCase): ...@@ -407,16 +435,21 @@ class TestRequest(MasterMixin, unittest.TestCase):
""" """
self.add_free_partition(2) self.add_free_partition(2)
self.assertNotEqual( self.assertNotEqual(
self.request('http://sr//', None, 'Maria', 'slappart2').__dict__, self.request('http://sr//', None, 'MyFirstInstance', 'slappart2').__dict__,
self.request('http://sr//', None, 'frontend', 'slappart2').__dict__) self.request('http://sr//', None, 'frontend', 'slappart2').__dict__)
class TestSlaveRequest(MasterMixin):
"""
Test requests related to slave instances.
"""
def test_slave_request_no_corresponding_partition(self): def test_slave_request_no_corresponding_partition(self):
""" """
Slave instance request will fail if no corresponding are found Slave instance request will fail if no corresponding are found
""" """
self.add_free_partition(2) self.add_free_partition(2)
with self.assertRaises(WrongFormat): rv = self._requestComputerPartition('http://sr//', None, 'MyFirstInstance', 'slappart2', shared=True)
self.request('http://sr//', None, 'Maria', 'slappart2', shared=True) self.assertEqual(rv._status_code, 404)
def test_slave_request_set_parameters(self): def test_slave_request_set_parameters(self):
""" """
...@@ -429,10 +462,10 @@ class TestRequest(MasterMixin, unittest.TestCase): ...@@ -429,10 +462,10 @@ class TestRequest(MasterMixin, unittest.TestCase):
self.add_free_partition(6) self.add_free_partition(6)
# Provide partition # Provide partition
master_partition_id = self.request('http://sr//', None, master_partition_id = self.request('http://sr//', None,
'Maria', 'slappart4')._partition_id 'MyFirstInstance', 'slappart4')._partition_id
# First request of slave instance # First request of slave instance
wanted_domain = 'fou.org' wanted_domain = 'fou.org'
self.request('http://sr//', None, 'Maria', 'slappart2', shared=True, self.request('http://sr//', None, 'MyFirstInstance', 'slappart2', shared=True,
partition_parameter_kw={'domain': wanted_domain}) partition_parameter_kw={'domain': wanted_domain})
# Get updated information for master partition # Get updated information for master partition
master_partition = self.getPartitionInformation(master_partition_id) master_partition = self.getPartitionInformation(master_partition_id)
...@@ -440,6 +473,17 @@ class TestRequest(MasterMixin, unittest.TestCase): ...@@ -440,6 +473,17 @@ class TestRequest(MasterMixin, unittest.TestCase):
our_slave = master_partition._parameter_dict['slave_instance_list'][0] our_slave = master_partition._parameter_dict['slave_instance_list'][0]
self.assertEqual(our_slave.get('domain'), wanted_domain) self.assertEqual(our_slave.get('domain'), wanted_domain)
def test_master_instance_with_no_slave(self):
"""
Test that a master instance with no requested slave
has an empty slave_instance_list parameter.
"""
self.add_free_partition(6)
# Provide partition
master_partition_id = self.request('http://sr//', None, 'MyMasterInstance', 'slappart4')._partition_id
master_partition = self.getPartitionInformation(master_partition_id)
self.assertEqual(len(master_partition._parameter_dict['slave_instance_list']), 0)
def test_slave_request_set_parameters_are_updated(self): def test_slave_request_set_parameters_are_updated(self):
""" """
Parameters sent in slave request must be put in slave master Parameters sent in slave request must be put in slave master
...@@ -454,10 +498,10 @@ class TestRequest(MasterMixin, unittest.TestCase): ...@@ -454,10 +498,10 @@ class TestRequest(MasterMixin, unittest.TestCase):
self.add_free_partition(6) self.add_free_partition(6)
# Provide partition # Provide partition
master_partition_id = self.request('http://sr//', None, master_partition_id = self.request('http://sr//', None,
'Maria', 'slappart4')._partition_id 'MyFirstInstance', 'slappart4')._partition_id
# First request of slave instance # First request of slave instance
wanted_domain_1 = 'crazy.org' wanted_domain_1 = 'crazy.org'
self.request('http://sr//', None, 'Maria', 'slappart2', shared=True, self.request('http://sr//', None, 'MyFirstInstance', 'slappart2', shared=True,
partition_parameter_kw={'domain': wanted_domain_1}) partition_parameter_kw={'domain': wanted_domain_1})
# Get updated information for master partition # Get updated information for master partition
master_partition = self.getPartitionInformation(master_partition_id) master_partition = self.getPartitionInformation(master_partition_id)
...@@ -466,7 +510,7 @@ class TestRequest(MasterMixin, unittest.TestCase): ...@@ -466,7 +510,7 @@ class TestRequest(MasterMixin, unittest.TestCase):
# Second request of slave instance # Second request of slave instance
wanted_domain_2 = 'maluco.org' wanted_domain_2 = 'maluco.org'
self.request('http://sr//', None, 'Maria', 'slappart2', shared=True, self.request('http://sr//', None, 'MyFirstInstance', 'slappart2', shared=True,
partition_parameter_kw={'domain': wanted_domain_2}) partition_parameter_kw={'domain': wanted_domain_2})
# Get updated information for master partition # Get updated information for master partition
master_partition = self.getPartitionInformation(master_partition_id) master_partition = self.getPartitionInformation(master_partition_id)
...@@ -475,6 +519,29 @@ class TestRequest(MasterMixin, unittest.TestCase): ...@@ -475,6 +519,29 @@ class TestRequest(MasterMixin, unittest.TestCase):
self.assertNotEqual(our_slave.get('domain'), wanted_domain_1) self.assertNotEqual(our_slave.get('domain'), wanted_domain_1)
self.assertEqual(our_slave.get('domain'), wanted_domain_2) self.assertEqual(our_slave.get('domain'), wanted_domain_2)
def test_slave_request_set_connection_parameters(self):
"""
Parameters set in slave instance by master instance must be put in slave instance connection parameters.
1. We request a slave instance
2. We set connection parameters for this slave instance
2. We check parameter is present when we do request() for the slave.
"""
self.add_free_partition(6)
# Provide partition
master_partition_id = self.request('http://sr//', None, 'MyMasterInstance', 'slappart4')._partition_id
# First request of slave instance
self.request('http://sr//', None, 'MySlaveInstance', 'slappart2', shared=True)
# Set connection parameter
master_partition = self.getPartitionInformation(master_partition_id)
# XXX change slave reference to be compatible with multiple nodes
self.setConnectionDict(partition_id=master_partition._partition_id,
connection_dict={'foo': 'bar'},
slave_reference=master_partition._parameter_dict['slave_instance_list'][0]['slave_reference'])
# Get updated information for slave partition
slave_partition = self.request('http://sr//', None, 'MySlaveInstance', 'slappart2', shared=True)
self.assertEqual(slave_partition.getConnectionParameter('foo'), 'bar')
def test_slave_request_one_corresponding_partition(self): def test_slave_request_one_corresponding_partition(self):
""" """
Successfull request slave instance follow these steps: Successfull request slave instance follow these steps:
...@@ -489,9 +556,9 @@ class TestRequest(MasterMixin, unittest.TestCase): ...@@ -489,9 +556,9 @@ class TestRequest(MasterMixin, unittest.TestCase):
self.add_free_partition(6) self.add_free_partition(6)
# Provide partition # Provide partition
master_partition_id = self.request('http://sr//', None, master_partition_id = self.request('http://sr//', None,
'Maria', 'slappart4')._partition_id 'MyFirstInstance', 'slappart4')._partition_id
# First request of slave instance # First request of slave instance
name = 'Maria' name = 'MyFirstInstance'
requester = 'slappart2' requester = 'slappart2'
our_slave = self.request('http://sr//', None, our_slave = self.request('http://sr//', None,
name, requester, shared=True) name, requester, shared=True)
...@@ -510,3 +577,354 @@ class TestRequest(MasterMixin, unittest.TestCase): ...@@ -510,3 +577,354 @@ class TestRequest(MasterMixin, unittest.TestCase):
name, requester, shared=True) name, requester, shared=True)
self.assertIsInstance(our_slave, slapos.slap.ComputerPartition) self.assertIsInstance(our_slave, slapos.slap.ComputerPartition)
self.assertEqual(slave_address, our_slave._connection_dict) self.assertEqual(slave_address, our_slave._connection_dict)
class TestMultiNodeSupport(MasterMixin):
def test_multi_node_support_different_software_release_list(self):
"""
Test that two different registered computers have their own
Software Release list.
"""
self.add_free_partition(6, computer_id='COMP-0')
self.add_free_partition(6, computer_id='COMP-1')
software_release_1_url = 'http://sr1'
software_release_2_url = 'http://sr2'
software_release_3_url = 'http://sr3'
self.supply(software_release_1_url, 'COMP-0')
self.supply(software_release_2_url, 'COMP-1')
self.supply(software_release_3_url, 'COMP-0')
self.supply(software_release_3_url, 'COMP-1')
computer_default = loads(self.app.get('/getFullComputerInformation?computer_id=%s' % self.computer_id).data)
computer_0 = loads(self.app.get('/getFullComputerInformation?computer_id=COMP-0').data)
computer_1 = loads(self.app.get('/getFullComputerInformation?computer_id=COMP-1').data)
self.assertEqual(len(computer_default._software_release_list), 0)
self.assertEqual(len(computer_0._software_release_list), 2)
self.assertEqual(len(computer_1._software_release_list), 2)
self.assertEqual(
computer_0._software_release_list[0]._software_release,
software_release_1_url
)
self.assertEqual(
computer_0._software_release_list[0]._computer_guid,
'COMP-0'
)
self.assertEqual(
computer_0._software_release_list[1]._software_release,
software_release_3_url
)
self.assertEqual(
computer_0._software_release_list[1]._computer_guid,
'COMP-0'
)
self.assertEqual(
computer_1._software_release_list[0]._software_release,
software_release_2_url
)
self.assertEqual(
computer_1._software_release_list[0]._computer_guid,
'COMP-1'
)
self.assertEqual(
computer_1._software_release_list[1]._software_release,
software_release_3_url
)
self.assertEqual(
computer_1._software_release_list[1]._computer_guid,
'COMP-1'
)
def test_multi_node_support_remove_software_release(self):
"""
Test that removing a software from a Computer doesn't
affect other computer
"""
software_release_url = 'http://sr'
self.add_free_partition(6, computer_id='COMP-0')
self.add_free_partition(6, computer_id='COMP-1')
self.supply(software_release_url, 'COMP-0')
self.supply(software_release_url, 'COMP-1')
self.supply(software_release_url, 'COMP-0', state='destroyed')
computer_0 = loads(self.app.get('/getFullComputerInformation?computer_id=COMP-0').data)
computer_1 = loads(self.app.get('/getFullComputerInformation?computer_id=COMP-1').data)
self.assertEqual(len(computer_0._software_release_list), 0)
self.assertEqual(len(computer_1._software_release_list), 1)
self.assertEqual(
computer_1._software_release_list[0]._software_release,
software_release_url
)
self.assertEqual(
computer_1._software_release_list[0]._computer_guid,
'COMP-1'
)
def test_multi_node_support_instance_default_computer(self):
"""
Test that instance request behaves correctly with default computer
"""
software_release_url = 'http://sr'
computer_0_id = 'COMP-0'
computer_1_id = 'COMP-1'
self.add_free_partition(6, computer_id=computer_0_id)
self.add_free_partition(6, computer_id=computer_1_id)
# Request without SLA -> goes to default computer only.
# It should fail if we didn't registered partitions for default computer
# (default computer is always registered)
rv = self._requestComputerPartition('http://sr//', None, 'MyFirstInstance', 'slappart2')
self.assertEqual(rv._status_code, 404)
rv = self._requestComputerPartition('http://sr//', None, 'MyFirstInstance', 'slappart2',
filter_kw={'computer_guid':self.computer_id})
self.assertEqual(rv._status_code, 404)
# Register default computer: deployment works
self.add_free_partition(1)
self.request('http://sr//', None, 'MyFirstInstance', 'slappart0')
computer_default = loads(self.app.get(
'/getFullComputerInformation?computer_id=%s' % self.computer_id).data)
self.assertEqual(len(computer_default._software_release_list), 0)
# No free space on default computer: request without SLA fails
rv = self._requestComputerPartition('http://sr//', None, 'CanIHasPartition', 'slappart2',
filter_kw={'computer_guid':self.computer_id})
self.assertEqual(rv._status_code, 404)
def test_multi_node_support_instance(self):
"""
Test that instance request behaves correctly with several
registered computers
"""
software_release_url = 'http://sr'
computer_0_id = 'COMP-0'
computer_1_id = 'COMP-1'
software_release_1 = 'http://sr//'
software_release_2 = 'http://othersr//'
self.add_free_partition(2, computer_id=computer_1_id)
# Deploy to first non-default computer using SLA
# It should fail since computer is not registered
rv = self._requestComputerPartition(software_release_1, None, 'MyFirstInstance', 'slappart2', filter_kw={'computer_guid':computer_0_id})
self.assertEqual(rv._status_code, 404)
self.add_free_partition(2, computer_id=computer_0_id)
# Deploy to first non-default computer using SLA
partition = self.request(software_release_1, None, 'MyFirstInstance', 'slappart0', filter_kw={'computer_guid':computer_0_id})
self.assertEqual(partition.getState(), 'started')
self.assertEqual(partition._partition_id, 'slappart0')
self.assertEqual(partition._computer_id, computer_0_id)
# All other instances should be empty
computer_0 = loads(self.app.get('/getFullComputerInformation?computer_id=COMP-0').data)
computer_1 = loads(self.app.get('/getFullComputerInformation?computer_id=COMP-1').data)
self.assertEqual(computer_0._computer_partition_list[0]._software_release_document._software_release, software_release_1)
self.assertTrue(computer_0._computer_partition_list[1]._software_release_document == None)
self.assertTrue(computer_1._computer_partition_list[0]._software_release_document == None)
self.assertTrue(computer_1._computer_partition_list[1]._software_release_document == None)
# Deploy to second non-default computer using SLA
partition = self.request(software_release_2, None, 'MySecondInstance', 'slappart0', filter_kw={'computer_guid':computer_1_id})
self.assertEqual(partition.getState(), 'started')
self.assertEqual(partition._partition_id, 'slappart0')
self.assertEqual(partition._computer_id, computer_1_id)
# The two remaining instances should be free, and MyfirstInstance should still be there
computer_0 = loads(self.app.get('/getFullComputerInformation?computer_id=COMP-0').data)
computer_1 = loads(self.app.get('/getFullComputerInformation?computer_id=COMP-1').data)
self.assertEqual(computer_0._computer_partition_list[0]._software_release_document._software_release, software_release_1)
self.assertTrue(computer_0._computer_partition_list[1]._software_release_document == None)
self.assertEqual(computer_1._computer_partition_list[0]._software_release_document._software_release, software_release_2)
self.assertTrue(computer_1._computer_partition_list[1]._software_release_document == None)
def test_multi_node_support_change_instance_state(self):
"""
Test that destroying an instance (i.e change state) from a Computer doesn't
affect other computer
"""
software_release_url = 'http://sr'
computer_0_id = 'COMP-0'
computer_1_id = 'COMP-1'
self.add_free_partition(6, computer_id=computer_0_id)
self.add_free_partition(6, computer_id=computer_1_id)
partition_first = self.request('http://sr//', None, 'MyFirstInstance', 'slappart0', filter_kw={'computer_guid':computer_0_id})
partition_second = self.request('http://sr//', None, 'MySecondInstance', 'slappart0', filter_kw={'computer_guid':computer_1_id})
partition_first = self.request('http://sr//', None, 'MyFirstInstance', 'slappart0', filter_kw={'computer_guid':computer_0_id}, state='stopped')
computer_0 = loads(self.app.get('/getFullComputerInformation?computer_id=COMP-0').data)
computer_1 = loads(self.app.get('/getFullComputerInformation?computer_id=COMP-1').data)
self.assertEqual(computer_0._computer_partition_list[0].getState(), 'stopped')
self.assertEqual(computer_0._computer_partition_list[1].getState(), 'destroyed')
self.assertEqual(computer_1._computer_partition_list[0].getState(), 'started')
self.assertEqual(computer_1._computer_partition_list[1].getState(), 'destroyed')
def test_multi_node_support_same_reference(self):
"""
Test that requesting an instance with same reference to two
different nodes behaves like master: once an instance is assigned to a node,
changing SLA will not change node.
"""
software_release_url = 'http://sr'
computer_0_id = 'COMP-0'
computer_1_id = 'COMP-1'
self.add_free_partition(2, computer_id=computer_0_id)
self.add_free_partition(2, computer_id=computer_1_id)
partition = self.request('http://sr//', None, 'MyFirstInstance', 'slappart0', filter_kw={'computer_guid':computer_0_id})
partition = self.request('http://sr//', None, 'MyFirstInstance', 'slappart0', filter_kw={'computer_guid':computer_1_id})
self.assertEqual(partition._computer_id, computer_0_id)
computer_1 = loads(self.app.get('/getFullComputerInformation?computer_id=COMP-1').data)
self.assertTrue(computer_1._computer_partition_list[0]._software_release_document == None)
self.assertTrue(computer_1._computer_partition_list[1]._software_release_document == None)
def test_multi_node_support_slave_instance(self):
"""
Test that slave instances are correctly deployed if SLA is specified
but deployed only on default computer if not specified (i.e not deployed
if default computer doesn't have corresponding master instance).
"""
computer_0_id = 'COMP-0'
computer_1_id = 'COMP-1'
self.add_free_partition(2, computer_id=computer_0_id)
self.add_free_partition(2, computer_id=computer_1_id)
self.add_free_partition(2)
self.request('http://sr2//', None, 'MyFirstInstance', 'slappart0', filter_kw={'computer_guid':computer_0_id})
self.request('http://sr//', None, 'MyOtherInstance', 'slappart0', filter_kw={'computer_guid':computer_1_id})
# Request slave without SLA: will fail
rv = self._requestComputerPartition('http://sr//', None, 'MySlaveInstance', 'slappart2', shared=True)
self.assertEqual(rv._status_code, 404)
# Request slave with SLA on incorrect computer: will fail
rv = self._requestComputerPartition('http://sr//', None, 'MySlaveInstance', 'slappart2', shared=True, filter_kw={'computer_guid':computer_0_id})
self.assertEqual(rv._status_code, 404)
# Request computer on correct computer: will succeed
partition = self.request('http://sr//', None, 'MySlaveInstance', 'slappart2', shared=True, filter_kw={'computer_guid':computer_1_id})
self.assertEqual(partition._computer_id, computer_1_id)
def test_multi_node_support_instance_guid(self):
"""
Test that instance_guid support behaves correctly with multiple nodes.
Warning: proxy doesn't gives unique id of instance, but gives instead unique id
of partition.
"""
computer_0_id = 'COMP-0'
computer_1_id = 'COMP-1'
self.add_free_partition(2, computer_id=computer_0_id)
self.add_free_partition(2, computer_id=computer_1_id)
self.add_free_partition(2)
partition_computer_0 = self.request('http://sr2//', None, 'MyFirstInstance', 'slappart0', filter_kw={'computer_guid':computer_0_id})
partition_computer_1 = self.request('http://sr//', None, 'MyOtherInstance', 'slappart0', filter_kw={'computer_guid':computer_1_id})
partition_computer_default = self.request('http://sr//', None, 'MyThirdInstance', 'slappart0')
self.assertEqual(partition_computer_0.getInstanceGuid(), 'COMP-0-slappart0')
self.assertEqual(partition_computer_1.getInstanceGuid(), 'COMP-1-slappart0')
self.assertEqual(partition_computer_default.getInstanceGuid(), 'computer-slappart0')
def test_multi_node_support_getComputerInformation(self):
"""
Test that computer information will not be given if computer is not registered.
Test that it still should work for the 'default' computer specified in slapos config
even if not yet registered.
Test that computer information is given if computer is registered.
"""
new_computer_id = '%s42' % self.computer_id
with self.assertRaises(slapos.slap.NotFoundError):
self.app.get('/getComputerInformation?computer_id=%s42' % new_computer_id)
try:
self.app.get('/getComputerInformation?computer_id=%s' % self.computer_id)
except slapos.slap.NotFoundError:
self.fail('Could not fetch informations for default computer.')
self.add_free_partition(1, computer_id=new_computer_id)
try:
self.app.get('/getComputerInformation?computer_id=%s' % new_computer_id)
except slapos.slap.NotFoundError:
self.fail('Could not fetch informations for registered computer.')
class TestMigrateVersion10To11(TestInformation, TestRequest, TestSlaveRequest, TestMultiNodeSupport):
"""
Test that old database version are automatically migrated without failure
"""
def setUp(self):
super(TestMigrateVersion10To11, self).setUp()
schema = pkg_resources.resource_stream('slapos.tests.slapproxy', 'database_dump_version_10.sql')
schema = schema.read() % dict(version='11')
self.db = sqlite3.connect(self.proxy_db)
self.db.cursor().executescript(schema)
self.db.commit()
def test_automatic_migration(self):
table_list = ('software11', 'computer11', 'partition11', 'slave11', 'partition_network11')
for table in table_list:
self.assertRaises(sqlite3.OperationalError, self.db.execute, "SELECT name FROM computer11")
# Run a dummy request to cause migration
self.app.get('/getComputerInformation?computer_id=computer')
# Check some partition parameters
self.assertEqual(
loads(self.app.get('/getComputerInformation?computer_id=computer').data)._computer_partition_list[0]._parameter_dict['slap_software_type'],
'production'
)
# Lower level tests
computer_list = self.db.execute("SELECT * FROM computer11").fetchall()
self.assertEqual(
computer_list,
[(u'computer', u'127.0.0.1', u'255.255.255.255')]
)
software_list = self.db.execute("SELECT * FROM software11").fetchall()
self.assertEqual(
software_list,
[(u'/srv/slapgrid//srv//runner/project//slapos/software.cfg', u'computer')]
)
partition_list = self.db.execute("select * from partition11").fetchall()
self.assertEqual(
partition_list,
[(u'slappart0', u'computer', u'busy', u'/srv/slapgrid//srv//runner/project//slapos/software.cfg', u'<?xml version=\'1.0\' encoding=\'utf-8\'?>\n<instance>\n <parameter id="json">{\n "site-id": "erp5"\n }\n}</parameter>\n</instance>\n', None, None, u'production', u'slapos', None, u'started'), (u'slappart1', u'computer', u'busy', u'/srv/slapgrid//srv//runner/project//slapos/software.cfg', u"<?xml version='1.0' encoding='utf-8'?>\n<instance/>\n", u'<?xml version=\'1.0\' encoding=\'utf-8\'?>\n<instance>\n <parameter id="url">mysql://127.0.0.1:45678/erp5</parameter>\n</instance>\n', None, u'mariadb', u'MariaDB DataBase', u'slappart0', u'started'), (u'slappart2', u'computer', u'busy', u'/srv/slapgrid//srv//runner/project//slapos/software.cfg', u'<?xml version=\'1.0\' encoding=\'utf-8\'?>\n<instance>\n <parameter id="cloudooo-json"></parameter>\n</instance>\n', u'<?xml version=\'1.0\' encoding=\'utf-8\'?>\n<instance>\n <parameter id="url">cloudooo://127.0.0.1:23000/</parameter>\n</instance>\n', None, u'cloudooo', u'Cloudooo', u'slappart0', u'started'), (u'slappart3', u'computer', u'busy', u'/srv/slapgrid//srv//runner/project//slapos/software.cfg', u"<?xml version='1.0' encoding='utf-8'?>\n<instance/>\n", u'<?xml version=\'1.0\' encoding=\'utf-8\'?>\n<instance>\n <parameter id="url">memcached://127.0.0.1:11000/</parameter>\n</instance>\n', None, u'memcached', u'Memcached', u'slappart0', u'started'), (u'slappart4', u'computer', u'busy', u'/srv/slapgrid//srv//runner/project//slapos/software.cfg', u"<?xml version='1.0' encoding='utf-8'?>\n<instance/>\n", u'<?xml version=\'1.0\' encoding=\'utf-8\'?>\n<instance>\n <parameter id="url">memcached://127.0.0.1:13301/</parameter>\n</instance>\n', None, u'kumofs', u'KumoFS', u'slappart0', u'started'), (u'slappart5', u'computer', u'busy', u'/srv/slapgrid//srv//runner/project//slapos/software.cfg', u'<?xml version=\'1.0\' encoding=\'utf-8\'?>\n<instance>\n <parameter id="kumofs-url">memcached://127.0.0.1:13301/</parameter>\n <parameter id="memcached-url">memcached://127.0.0.1:11000/</parameter>\n <parameter id="cloudooo-url">cloudooo://127.0.0.1:23000/</parameter>\n</instance>\n', u'<?xml version=\'1.0\' encoding=\'utf-8\'?>\n<instance>\n <parameter id="url">https://[fc00::1]:10001</parameter>\n</instance>\n', None, u'tidstorage', u'TidStorage', u'slappart0', u'started'), (u'slappart6', u'computer', u'free', None, None, None, None, None, None, None, u'started'), (u'slappart7', u'computer', u'free', None, None, None, None, None, None, None, u'started'), (u'slappart8', u'computer', u'free', None, None, None, None, None, None, None, u'started'), (u'slappart9', u'computer', u'free', None, None, None, None, None, None, None, u'started')]
)
slave_list = self.db.execute("select * from slave11").fetchall()
self.assertEqual(
slave_list,
[]
)
partition_network_list = self.db.execute("select * from partition_network11").fetchall()
self.assertEqual(
partition_network_list,
[(u'slappart0', u'computer', u'slappart0', u'127.0.0.1', u'255.255.255.255'), (u'slappart0', u'computer', u'slappart0', u'fc00::1', u'ffff:ffff:ffff::'), (u'slappart1', u'computer', u'slappart1', u'127.0.0.1', u'255.255.255.255'), (u'slappart1', u'computer', u'slappart1', u'fc00::1', u'ffff:ffff:ffff::'), (u'slappart2', u'computer', u'slappart2', u'127.0.0.1', u'255.255.255.255'), (u'slappart2', u'computer', u'slappart2', u'fc00::1', u'ffff:ffff:ffff::'), (u'slappart3', u'computer', u'slappart3', u'127.0.0.1', u'255.255.255.255'), (u'slappart3', u'computer', u'slappart3', u'fc00::1', u'ffff:ffff:ffff::'), (u'slappart4', u'computer', u'slappart4', u'127.0.0.1', u'255.255.255.255'), (u'slappart4', u'computer', u'slappart4', u'fc00::1', u'ffff:ffff:ffff::'), (u'slappart5', u'computer', u'slappart5', u'127.0.0.1', u'255.255.255.255'), (u'slappart5', u'computer', u'slappart5', u'fc00::1', u'ffff:ffff:ffff::'), (u'slappart6', u'computer', u'slappart6', u'127.0.0.1', u'255.255.255.255'), (u'slappart6', u'computer', u'slappart6', u'fc00::1', u'ffff:ffff:ffff::'), (u'slappart7', u'computer', u'slappart7', u'127.0.0.1', u'255.255.255.255'), (u'slappart7', u'computer', u'slappart7', u'fc00::1', u'ffff:ffff:ffff::'), (u'slappart8', u'computer', u'slappart8', u'127.0.0.1', u'255.255.255.255'), (u'slappart8', u'computer', u'slappart8', u'fc00::1', u'ffff:ffff:ffff::'), (u'slappart9', u'computer', u'slappart9', u'127.0.0.1', u'255.255.255.255'), (u'slappart9', u'computer', u'slappart9', u'fc00::1', u'ffff:ffff:ffff::')]
)
# Override several tests that needs an empty database
@unittest.skip("Not implemented")
def test_multi_node_support_different_software_release_list(self):
pass
@unittest.skip("Not implemented")
def test_multi_node_support_instance_default_computer(self):
pass
@unittest.skip("Not implemented")
def test_multi_node_support_instance_guid(self):
pass
@unittest.skip("Not implemented")
def test_partition_are_empty(self):
pass
@unittest.skip("Not implemented")
def test_request_consistent_parameters(self):
pass
-- Real world example of webrunner database running version 10 of proxy db.
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE software10 (url VARCHAR(255) UNIQUE);
INSERT INTO "software10" VALUES('/srv/slapgrid//srv//runner/project//slapos/software.cfg');
CREATE TABLE computer10 (
address VARCHAR(255),
netmask VARCHAR(255),
CONSTRAINT uniq PRIMARY KEY (address, netmask));
INSERT INTO "computer10" VALUES('127.0.0.1','255.255.255.255');
CREATE TABLE partition10 (
reference VARCHAR(255) UNIQUE,
slap_state VARCHAR(255) DEFAULT 'free',
software_release VARCHAR(255),
xml TEXT,
connection_xml TEXT,
slave_instance_list TEXT,
software_type VARCHAR(255),
partition_reference VARCHAR(255),
requested_by VARCHAR(255), -- only used for debugging,
-- slapproxy does not support proper scope
requested_state VARCHAR(255) NOT NULL DEFAULT 'started'
);
INSERT INTO "partition10" VALUES('slappart0','busy','/srv/slapgrid//srv//runner/project//slapos/software.cfg','<?xml version=''1.0'' encoding=''utf-8''?>
<instance>
<parameter id="json">{
"site-id": "erp5"
}
}</parameter>
</instance>
',NULL,NULL,'production','slapos',NULL,'started');
INSERT INTO "partition10" VALUES('slappart1','busy','/srv/slapgrid//srv//runner/project//slapos/software.cfg','<?xml version=''1.0'' encoding=''utf-8''?>
<instance/>
','<?xml version=''1.0'' encoding=''utf-8''?>
<instance>
<parameter id="url">mysql://127.0.0.1:45678/erp5</parameter>
</instance>
',NULL,'mariadb','MariaDB DataBase','slappart0','started');
INSERT INTO "partition10" VALUES('slappart2','busy','/srv/slapgrid//srv//runner/project//slapos/software.cfg','<?xml version=''1.0'' encoding=''utf-8''?>
<instance>
<parameter id="cloudooo-json"></parameter>
</instance>
','<?xml version=''1.0'' encoding=''utf-8''?>
<instance>
<parameter id="url">cloudooo://127.0.0.1:23000/</parameter>
</instance>
',NULL,'cloudooo','Cloudooo','slappart0','started');
INSERT INTO "partition10" VALUES('slappart3','busy','/srv/slapgrid//srv//runner/project//slapos/software.cfg','<?xml version=''1.0'' encoding=''utf-8''?>
<instance/>
','<?xml version=''1.0'' encoding=''utf-8''?>
<instance>
<parameter id="url">memcached://127.0.0.1:11000/</parameter>
</instance>
',NULL,'memcached','Memcached','slappart0','started');
INSERT INTO "partition10" VALUES('slappart4','busy','/srv/slapgrid//srv//runner/project//slapos/software.cfg','<?xml version=''1.0'' encoding=''utf-8''?>
<instance/>
','<?xml version=''1.0'' encoding=''utf-8''?>
<instance>
<parameter id="url">memcached://127.0.0.1:13301/</parameter>
</instance>
',NULL,'kumofs','KumoFS','slappart0','started');
INSERT INTO "partition10" VALUES('slappart5','busy','/srv/slapgrid//srv//runner/project//slapos/software.cfg','<?xml version=''1.0'' encoding=''utf-8''?>
<instance>
<parameter id="kumofs-url">memcached://127.0.0.1:13301/</parameter>
<parameter id="memcached-url">memcached://127.0.0.1:11000/</parameter>
<parameter id="cloudooo-url">cloudooo://127.0.0.1:23000/</parameter>
</instance>
','<?xml version=''1.0'' encoding=''utf-8''?>
<instance>
<parameter id="url">https://[fc00::1]:10001</parameter>
</instance>
',NULL,'tidstorage','TidStorage','slappart0','started');
INSERT INTO "partition10" VALUES('slappart6','free',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'started');
INSERT INTO "partition10" VALUES('slappart7','free',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'started');
INSERT INTO "partition10" VALUES('slappart8','free',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'started');
INSERT INTO "partition10" VALUES('slappart9','free',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'started');
CREATE TABLE slave10 (
reference VARCHAR(255) UNIQUE,
connection_xml TEXT,
hosted_by VARCHAR(255),
asked_by VARCHAR(255) -- only used for debugging,
-- slapproxy does not support proper scope
);
CREATE TABLE partition_network10 (
partition_reference VARCHAR(255),
reference VARCHAR(255),
address VARCHAR(255),
netmask VARCHAR(255)
);
INSERT INTO "partition_network10" VALUES('slappart0','slappart0','127.0.0.1','255.255.255.255');
INSERT INTO "partition_network10" VALUES('slappart0','slappart0','fc00::1','ffff:ffff:ffff::');
INSERT INTO "partition_network10" VALUES('slappart1','slappart1','127.0.0.1','255.255.255.255');
INSERT INTO "partition_network10" VALUES('slappart1','slappart1','fc00::1','ffff:ffff:ffff::');
INSERT INTO "partition_network10" VALUES('slappart2','slappart2','127.0.0.1','255.255.255.255');
INSERT INTO "partition_network10" VALUES('slappart2','slappart2','fc00::1','ffff:ffff:ffff::');
INSERT INTO "partition_network10" VALUES('slappart3','slappart3','127.0.0.1','255.255.255.255');
INSERT INTO "partition_network10" VALUES('slappart3','slappart3','fc00::1','ffff:ffff:ffff::');
INSERT INTO "partition_network10" VALUES('slappart4','slappart4','127.0.0.1','255.255.255.255');
INSERT INTO "partition_network10" VALUES('slappart4','slappart4','fc00::1','ffff:ffff:ffff::');
INSERT INTO "partition_network10" VALUES('slappart5','slappart5','127.0.0.1','255.255.255.255');
INSERT INTO "partition_network10" VALUES('slappart5','slappart5','fc00::1','ffff:ffff:ffff::');
INSERT INTO "partition_network10" VALUES('slappart6','slappart6','127.0.0.1','255.255.255.255');
INSERT INTO "partition_network10" VALUES('slappart6','slappart6','fc00::1','ffff:ffff:ffff::');
INSERT INTO "partition_network10" VALUES('slappart7','slappart7','127.0.0.1','255.255.255.255');
INSERT INTO "partition_network10" VALUES('slappart7','slappart7','fc00::1','ffff:ffff:ffff::');
INSERT INTO "partition_network10" VALUES('slappart8','slappart8','127.0.0.1','255.255.255.255');
INSERT INTO "partition_network10" VALUES('slappart8','slappart8','fc00::1','ffff:ffff:ffff::');
INSERT INTO "partition_network10" VALUES('slappart9','slappart9','127.0.0.1','255.255.255.255');
INSERT INTO "partition_network10" VALUES('slappart9','slappart9','fc00::1','ffff:ffff:ffff::');
COMMIT;
...@@ -26,4 +26,4 @@ ...@@ -26,4 +26,4 @@
# #
############################################################################## ##############################################################################
version = '1.1.2' version = '1.2.1'
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