Commit 3f737526 authored by Alain Takoudjou's avatar Alain Takoudjou Committed by Rafael Monnerat

Improve "Unavailable Computer" Support Request

parent 2e3a0761
...@@ -32,7 +32,9 @@ ...@@ -32,7 +32,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 +44,7 @@ ...@@ -42,9 +44,7 @@
</item> </item>
<item> <item>
<key> <string>periodicity_minute_frequency</string> </key> <key> <string>periodicity_minute_frequency</string> </key>
<value> <value> <int>30</int> </value>
<none/>
</value>
</item> </item>
<item> <item>
<key> <string>periodicity_month</string> </key> <key> <string>periodicity_month</string> </key>
......
...@@ -80,7 +80,7 @@ if not is_service_provider:\n ...@@ -80,7 +80,7 @@ if not is_service_provider:\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 = \'Allocation scope has been changed for %s\' % computer_reference\n request_title = \'[MONITORING] Allocation scope has been changed for %s\' % computer_reference\n
request_description = \'Allocation scope has been changed back to \' \\\n request_description = \'Allocation scope has been changed back to \' \\\n
\'open/personal for %s\' % computer_reference\n \'open/personal for %s\' % computer_reference\n
message_title = \'We have changed allocation scope for %s\' % computer_reference\n message_title = \'We have changed allocation scope for %s\' % computer_reference\n
......
...@@ -62,29 +62,72 @@ if portal.ERP5Site_isSupportRequestCreationClosed():\n ...@@ -62,29 +62,72 @@ if portal.ERP5Site_isSupportRequestCreationClosed():\n
return\n return\n
\n \n
reference = context.getReference()\n reference = context.getReference()\n
computer_title = context.getTitle()\n
ticket_title = "[MONITORING] Lost contact with computer %s" % reference\n
description = ""\n
should_notify = True\n
last_contact = "No Contact Information"\n
\n
memcached_dict = context.getPortalObject().portal_memcached.getMemcachedDict(\n memcached_dict = context.getPortalObject().portal_memcached.getMemcachedDict(\n
key_prefix=\'slap_tool\',\n key_prefix=\'slap_tool\',\n
plugin_path=\'portal_memcached/default_memcached_plugin\')\n plugin_path=\'portal_memcached/default_memcached_plugin\')\n
\n \n
try:\n try:\n
d = memcached_dict[reference]\n d = memcached_dict[reference]\n
d = json.loads(d)\n
last_contact = DateTime(d.get(\'created_at\'))\n
if (DateTime() - last_contact) > 1:\n
description = "The Computer %s (%s) has not contacted the server for more than 24 hours" \\\n
"(last contact date: %s)" % (computer_title, reference, last_contact)\n
else:\n
should_notify = False\n
except KeyError:\n except KeyError:\n
return context.Base_generateSupportRequestForSlapOS(\n ticket_title = "[MONITORING] No information about %s" % reference\n
"No information about %s" % reference,\n description = "The Computer %s (%s) has not contacted the server (No Contact Information)" % (\n
"%s has not contacted the server (No Contact Information)" % reference,\n computer_title, reference)\n
context.getRelativeUrl()\n
)\n
\n \n
\n \n
d = json.loads(d)\n if should_notify:\n
last_contact = DateTime(d.get(\'created_at\'))\n support_request_url = context.Base_generateSupportRequestForSlapOS(\n
\n ticket_title,\n
if (DateTime() - last_contact) > 1:\n description,\n
return context.Base_generateSupportRequestForSlapOS(\n
"Lost contact with %s" % reference,\n
"%s has not contacted the server for more than 24 hours (last contact date: %s)" % (reference, last_contact),\n
context.getRelativeUrl()\n context.getRelativeUrl()\n
)\n )\n
\n
support_request = None\n
person = context.getSourceAdministrationValue(portal_type="Person")\n
if not person:\n
return support_request_url\n
\n
if support_request_url:\n
support_request = portal.restrictedTraverse(support_request_url, None)\n
else:\n
# XXX - the support request might already exists\n
support_request = portal.portal_catalog.getResultValue(\n
portal_type = \'Support Request\',\n
title = ticket_title,\n
simulation_state = \'validated\',\n
source_project_uid = context.getUid()\n
)\n
if support_request is None:\n
# Existing ticket not found, can not create event for the moment\n
return support_request_url\n
\n
# Send Notification message\n
notification_reference = \'slapos-crm-computer_check_state.notification\'\n
notification_message = portal.portal_notifications.getDocumentValue(\n
reference=notification_reference)\n
mapping_dict = {\'computer_title\':context.getTitle(),\n
\'computer_id\':reference,\n
\'last_contact\':last_contact}\n
message = notification_message.asText(\n
substitution_method_parameter_dict={\'mapping_dict\':mapping_dict})\n
\n
support_request.SupportRequest_trySendNotificationMessage(\n
ticket_title.replace(\'[MONITORING] \', \'\'),\n
message, person.getRelativeUrl(), 5)\n
\n
return support_request_url\n
]]></string> </value> ]]></string> </value>
......
...@@ -62,7 +62,7 @@ last_event = context.portal_catalog.getResultValue(\n ...@@ -62,7 +62,7 @@ last_event = context.portal_catalog.getResultValue(\n
sort_on=[(\'delivery.start_date\', \'DESC\')],\n sort_on=[(\'delivery.start_date\', \'DESC\')],\n
)\n )\n
if last_event and \\\n if last_event and \\\n
(DateTime() - last_event.getStartDate() < 1):\n (DateTime() - last_event.getStartDate() < interval_of_day):\n
# User has already been notified this last 24h.\n # User has already been notified this last 24h.\n
return\n return\n
event = portal.event_module.slapos_crm_web_message_template.\\\n event = portal.event_module.slapos_crm_web_message_template.\\\n
...@@ -77,13 +77,15 @@ event.edit(\n ...@@ -77,13 +77,15 @@ event.edit(\n
)\n )\n
event.stop()\n event.stop()\n
event.deliver()\n event.deliver()\n
\n
return event\n
]]></string> </value> ]]></string> </value>
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>message_title, message, source_relative_url</string> </value> <value> <string>message_title, message, source_relative_url, interval_of_day=1</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
...@@ -7,6 +7,7 @@ from DateTime import DateTime ...@@ -7,6 +7,7 @@ from DateTime import DateTime
from functools import wraps from functools import wraps
from Products.ERP5Type.tests.utils import createZODBPythonScript from Products.ERP5Type.tests.utils import createZODBPythonScript
import difflib import difflib
import json
def simulate(script_id, params_string, code_string): def simulate(script_id, params_string, code_string):
def upperWrap(f): def upperWrap(f):
...@@ -1798,8 +1799,8 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin): ...@@ -1798,8 +1799,8 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin):
def _cancelTestSupportRequestList(self): def _cancelTestSupportRequestList(self):
for support_request in self.portal.portal_catalog( for support_request in self.portal.portal_catalog(
portal_type="Support Request", portal_type="Support Request",
title="Allocation scope has been changed for TESTCOMPT%", title="[MONITORING] % TESTCOMPT-%",
simulation_state="suspended"): simulation_state=["validated", "suspended"]):
support_request.invalidate() support_request.invalidate()
self.tic() self.tic()
...@@ -1862,13 +1863,12 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin): ...@@ -1862,13 +1863,12 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin):
'return context.restrictedTraverse(' \ 'return context.restrictedTraverse(' \
'context.REQUEST["test_computerNotAllowedAllocationScope_OpenPublic"])') 'context.REQUEST["test_computerNotAllowedAllocationScope_OpenPublic"])')
@simulate('SupportRequest_trySendNotificationMessage', @simulate('SupportRequest_trySendNotificationMessage',
'message_title, message, source_relative_url', 'message_title, message, source_relative_url, interval_of_day=1',
'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" % (message_title, message, source_relative_url))') '%s %s %s %s" % (message_title, message, source_relative_url, interval_of_day))')
def test_computerNotAllowedAllocationScope_OpenPublic(self): def test_computerNotAllowedAllocationScope_OpenPublic(self):
new_id = self.generateNewId()
computer = self._makeComputer(self.new_id) computer = self._makeComputer(self.new_id)
person = computer.getSourceAdministrationValue() person = computer.getSourceAdministrationValue()
self._updatePersonAssignment(person, 'role/member') self._updatePersonAssignment(person, 'role/member')
...@@ -1883,9 +1883,9 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin): ...@@ -1883,9 +1883,9 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin):
ticket = self._getGeneratedSupportRequest(computer) ticket = self._getGeneratedSupportRequest(computer)
self.assertEquals(ticket.getSimulationState(), 'suspended') self.assertEquals(ticket.getSimulationState(), 'suspended')
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \ self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s' % \ '%s %s %s %s' % \
('We have changed allocation scope for %s' % computer.getReference(), ('We have changed allocation scope for %s' % computer.getReference(),
'Test NM content\n%s\n' % computer.getReference(), person.getRelativeUrl()), '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'])
...@@ -1895,13 +1895,12 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin): ...@@ -1895,13 +1895,12 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin):
'return context.restrictedTraverse(' \ 'return context.restrictedTraverse(' \
'context.REQUEST["test_computerNotAllowedAllocationScope_OpenFriend"])') 'context.REQUEST["test_computerNotAllowedAllocationScope_OpenFriend"])')
@simulate('SupportRequest_trySendNotificationMessage', @simulate('SupportRequest_trySendNotificationMessage',
'message_title, message, source_relative_url', 'message_title, message, source_relative_url, interval_of_day=1',
'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" % (message_title, message, source_relative_url))') '%s %s %s %s" % (message_title, message, source_relative_url, interval_of_day))')
def test_computerNotAllowedAllocationScope_OpenFriend(self): def test_computerNotAllowedAllocationScope_OpenFriend(self):
new_id = self.generateNewId()
computer = self._makeComputer(self.new_id) computer = self._makeComputer(self.new_id)
person = computer.getSourceAdministrationValue() person = computer.getSourceAdministrationValue()
self._updatePersonAssignment(person, 'role/member') self._updatePersonAssignment(person, 'role/member')
...@@ -1918,9 +1917,9 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin): ...@@ -1918,9 +1917,9 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin):
ticket = self._getGeneratedSupportRequest(computer) ticket = self._getGeneratedSupportRequest(computer)
self.assertEquals(ticket.getSimulationState(), 'suspended') self.assertEquals(ticket.getSimulationState(), 'suspended')
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \ self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s' % \ '%s %s %s %s' % \
('We have changed allocation scope for %s' % computer.getReference(), ('We have changed allocation scope for %s' % computer.getReference(),
'Test NM content\n%s\n' % computer.getReference(), person.getRelativeUrl()), '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'])
...@@ -1956,4 +1955,182 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin): ...@@ -1956,4 +1955,182 @@ class TestSlapOSComputer_notifyWrongAllocationScope(testSlapOSMixin):
destination_section=friend_person.getRelativeUrl()) destination_section=friend_person.getRelativeUrl())
computer.Computer_checkAndUpdateAllocationScope() computer.Computer_checkAndUpdateAllocationScope()
self.tic() self.tic()
self.assertEquals(computer.getAllocationScope(), 'open/friend') self.assertEquals(computer.getAllocationScope(), 'open/friend')
\ No newline at end of file
class TestSlapOSComputer_CheckState(testSlapOSMixin):
def beforeTearDown(self):
self._cancelTestSupportRequestList()
transaction.abort()
def afterSetUp(self):
super(TestSlapOSComputer_CheckState, self).afterSetUp()
self.new_id = self.generateNewId()
self._cancelTestSupportRequestList()
def _cancelTestSupportRequestList(self):
for support_request in self.portal.portal_catalog(
portal_type="Support Request",
title="[MONITORING] % TESTCOMPT-%",
simulation_state=["validated", "suspended"]):
support_request.invalidate()
self.tic()
def _makeNotificationMessage(self, reference):
notification_message = self.portal.notification_message_module.newContent(
portal_type="Notification Message",
title='The Computer %s has not contacted the server for more than 24 hours' % reference,
text_content='Test NM content<br/>%s<br/>' % reference,
content_type='text/html',
)
return notification_message.getRelativeUrl()
def _getGeneratedSupportRequest(self, computer_uid, request_title):
support_request = self.portal.portal_catalog.getResultValue(
portal_type = 'Support Request',
title = request_title,
simulation_state = 'validated',
source_project_uid = computer_uid
)
return support_request
def _makeComputer(self,new_id):
# Clone computer document
person = self.portal.person_module.template_member\
.Base_createCloneDocument(batch_mode=1)
computer = self.portal.computer_module\
.template_computer.Base_createCloneDocument(batch_mode=1)
computer.edit(
title="computer ticket %s" % (new_id, ),
reference="TESTCOMPT-%s" % (new_id, ),
source_administration_value=person
)
computer.validate()
return computer
def _simulateBase_generateSupportRequestForSlapOS(self):
script_name = 'Base_generateSupportRequestForSlapOS'
if script_name in self.portal.portal_skins.custom.objectIds():
raise ValueError('Precondition failed: %s exists in custom' % script_name)
createZODBPythonScript(self.portal.portal_skins.custom,
script_name,
'*args, **kw',
'# Script body\n'
"""return 'Visited Base_generateSupportRequestForSlapOS'""")
transaction.commit()
def _dropBase_generateSupportRequestForSlapOS(self):
script_name = 'Base_generateSupportRequestForSlapOS'
if script_name in self.portal.portal_skins.custom.objectIds():
self.portal.portal_skins.custom.manage_delObjects(script_name)
transaction.commit()
self.assertFalse(script_name in self.portal.portal_skins.custom.objectIds())
def test_Computer_checkState_call_support_request(self):
computer = self._makeComputer(self.new_id)
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
memcached_dict[computer.getReference()] = json.dumps(
{"created_at":"%s" % (DateTime() - 1.1)}
)
self._simulateBase_generateSupportRequestForSlapOS()
try:
result = computer.Computer_checkState()
finally:
self._dropBase_generateSupportRequestForSlapOS()
self.assertEqual('Visited Base_generateSupportRequestForSlapOS',
result)
def test_Computer_checkState_empty_cache(self):
computer = self._makeComputer(self.new_id)
self._simulateBase_generateSupportRequestForSlapOS()
try:
result = computer.Computer_checkState()
finally:
self._dropBase_generateSupportRequestForSlapOS()
self.assertEqual('Visited Base_generateSupportRequestForSlapOS',
result)
@simulate('NotificationTool_getDocumentValue',
'reference=None',
'assert reference == "slapos-crm-computer_check_state.notification"\n' \
'return context.restrictedTraverse(' \
'context.REQUEST["test_Computer_checkState_notify"])')
@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))')
def test_Computer_checkState_notify(self):
computer = self._makeComputer(self.new_id)
person = computer.getSourceAdministrationValue()
memcached_dict = self.portal.portal_memcached.getMemcachedDict(
key_prefix='slap_tool',
plugin_path='portal_memcached/default_memcached_plugin')
memcached_dict[computer.getReference()] = json.dumps(
{"created_at":"%s" % (DateTime() - 1.1)}
)
message_interval_per_day = 5
self.portal.REQUEST['test_Computer_checkState_notify'] = \
self._makeNotificationMessage(computer.getReference())
computer.Computer_checkState()
self.tic()
ticket_title = "[MONITORING] Lost contact with computer %s" % computer.getReference()
ticket = self._getGeneratedSupportRequest(computer.getUid(), ticket_title)
self.assertNotEqual(ticket, None)
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s %d' % ( \
ticket_title.replace('[MONITORING] ', ''),
'Test NM content\n%s\n' % computer.getReference(),
person.getRelativeUrl(), message_interval_per_day),
ticket.workflow_history['edit_workflow'][-1]['comment'])
@simulate('NotificationTool_getDocumentValue',
'reference=None',
'assert reference == "slapos-crm-computer_check_state.notification"\n' \
'return context.restrictedTraverse(' \
'context.REQUEST["test_Computer_checkState_empty_cache_notify"])')
@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))')
def test_Computer_checkState_empty_cache_notify(self):
computer = self._makeComputer(self.new_id)
person = computer.getSourceAdministrationValue()
message_interval_per_day = 5
self.portal.REQUEST['test_Computer_checkState_empty_cache_notify'] = \
self._makeNotificationMessage(computer.getReference())
computer.Computer_checkState()
self.tic()
ticket_title = "[MONITORING] No information about %s" % computer.getReference()
ticket = self._getGeneratedSupportRequest(computer.getUid(), ticket_title)
self.assertNotEqual(ticket, None)
self.assertEqual('Visited by SupportRequest_trySendNotificationMessage ' \
'%s %s %s %d' % ( \
ticket_title.replace('[MONITORING] ', ''),
'Test NM content\n%s\n' % computer.getReference(),
person.getRelativeUrl(), message_interval_per_day),
ticket.workflow_history['edit_workflow'][-1]['comment'])
\ No newline at end of file
...@@ -325,6 +325,47 @@ class TestSlapOSCloudSupportRequestGeneration(testSlapOSMixin): ...@@ -325,6 +325,47 @@ class TestSlapOSCloudSupportRequestGeneration(testSlapOSMixin):
self.assertEqual('Visited Base_generateSupportRequestForSlapOS', self.assertEqual('Visited Base_generateSupportRequestForSlapOS',
result) result)
def test_SupportRequest_trySendNotificationMessage(self):
title = "Test Support Request %s" % self.new_id
text_content='Test NM content<br/>%s<br/>' % self.new_id
computer = self._makeComputer(self.new_id)
support_request_url = computer.Base_generateSupportRequestForSlapOS(
title, title, computer.getRelativeUrl()
)
support_request = self.portal.restrictedTraverse(support_request_url)
person = computer.getSourceAdministrationValue()
time_before_next = 2
self.tic()
first_event = support_request.SupportRequest_trySendNotificationMessage(
message_title=title, message=text_content,
source_relative_url=person.getRelativeUrl(),
interval_of_day=time_before_next
)
self.assertNotEqual(first_event, None)
first_event.edit(start_date=(DateTime() - 1.8))
self.tic()
event = support_request.SupportRequest_trySendNotificationMessage(
message_title=title, message=text_content,
source_relative_url=person.getRelativeUrl(),
interval_of_day=time_before_next
)
self.assertEqual(event, None)
time_before_next = 1
event = support_request.SupportRequest_trySendNotificationMessage(
message_title=title, message=text_content,
source_relative_url=person.getRelativeUrl(),
interval_of_day=time_before_next
)
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)
......
42 43
\ No newline at end of file \ No newline at end of file
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