Commit 878461b9 authored by Łukasz Nowak's avatar Łukasz Nowak

Implement cyclic software instance tree protection.

parent 3dd464ba
......@@ -34,6 +34,9 @@ import collections
class DisconnectedSoftwareTree(Exception):
pass
class CyclicSoftwareTree(Exception):
pass
class SoftwareInstance(Item):
"""
"""
......@@ -65,6 +68,27 @@ class SoftwareInstance(Item):
result_dict[key] = value
return result_dict
security.declareProtected(Permissions.AccessContentsInformation,
'checkNotCyclic')
def checkNotCyclic(self, graph):
# see http://neopythonic.blogspot.com/2009/01/detecting-cycles-in-directed-graph.html
todo = set(graph.keys())
while todo:
node = todo.pop()
stack = [node]
while stack:
top = stack[-1]
for node in graph[top]:
if node in stack:
raise CyclicSoftwareTree
if node in todo:
stack.append(node)
todo.remove(node)
break
else:
node = stack.pop()
return True
security.declareProtected(Permissions.AccessContentsInformation,
'checkConnected')
def checkConnected(self, graph, root):
......
......@@ -152,7 +152,8 @@ if not request_software_instance.getUid() in graph:\n
graph[software_instance.getUid()] = software_instance.getPredecessorUidList() + [request_software_instance.getUid()]\n
\n
# check if all elements are still connected\n
script.log(graph, root_software_instance.getUid())\n
script.log(graph)\n
software_instance.checkNotCyclic(graph)\n
software_instance.checkConnected(graph, root_software_instance.getUid())\n
\n
software_instance.edit(\n
......
249
\ No newline at end of file
250
\ No newline at end of file
......@@ -8199,6 +8199,156 @@ class TestVifibSlapWebService(testVifibMixin):
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
def stepDirectRequestComputerPartitionRaisesCyclicSoftwareTree(self,
sequence, **kw):
software_instance = self.portal.portal_catalog.getResultValue(
uid = sequence['software_instance_uid'])
requested_reference = sequence['requested_reference']
from erp5.document.SoftwareInstance import CyclicSoftwareTree
self.assertRaises(CyclicSoftwareTree,
software_instance.requestSoftwareInstance,
software_release=sequence['software_release_uri'],
software_type=sequence['requested_reference'],
partition_reference=sequence['requested_reference'],
shared=False,
instance_xml=self.minimal_correct_xml,
sla_xml=self.minimal_correct_xml,
state='started'
)
def test_bug_cyclic_software_instance(self):
"""Check that no cyclic Software Instance trees would be created
In below scenario system shall behave like mentioned:
OpenOrder.request(SR, A) | SR(A)
A.request(SR, B) | SR(A) <- SR(B)
B.request(SR, A) | SR(A) <- SR(B) <- SR(C)
C.request(SR, B) raises immediately, because the result would be:
SR(A)
SR(B) <-> SR(C)
so B and C would be cyclic
"""
# Setup sufficient amount of CP
self.computer_partition_amount = 3
sequence_list = SequenceList()
sequence_string = """
# Prepare software release
LoginTestVifibDeveloper
SelectNewSoftwareReleaseUri
CreateSoftwareRelease
Tic
SubmitSoftwareRelease
Tic
CreateSoftwareProduct
Tic
ValidateSoftwareProduct
Tic
SetSoftwareProductToSoftwareRelease
PublishByActionSoftwareRelease
Logout
# Create the computer
LoginTestVifibAdmin
CreateComputer
Tic
Logout
SlapLoginCurrentComputer
FormatComputer
Tic
SlapLogout
StoreCurrentComputerReferenceBufferA
StoreCurrentComputerUidBufferA
# Install the software release
LoginTestVifibAdmin
RequestSoftwareInstallation
Tic
Logout
SlapLoginCurrentComputer
ComputerSoftwareReleaseAvailable
Tic
SlapLogout
# Create Software Instance A (originates from Open Order)
LoginTestVifibCustomer
PersonRequestSoftwareInstance
Tic
Logout
LoginDefaultUser
ConfirmOrderedSaleOrderActiveSense
Tic
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
Logout
LoginDefaultUser
CheckComputerPartitionInstanceSetupSalePackingListConfirmed
Logout
# From root request B
SelectRequestedReferenceB
SlapLoginCurrentSoftwareInstance
RequestComputerPartitionNotReadyResponse
Tic
SlapLogout
SlapLoginCurrentSoftwareInstance
RequestComputerPartition
Tic
SlapLogout
LoginDefaultUser
CheckSoftwareInstanceAndRelatedComputerPartitionNoPackingListCheck
CheckRequestedSoftwareInstanceAndRelatedComputerPartition
Logout
LoginDefaultUser
SetCurrentSoftwareInstanceRequested
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
Logout
SlapLoginCurrentSoftwareInstance
CheckRequestedComputerPartitionCleanParameterList
Logout
# From B request C
SelectRequestedReferenceC
SlapLoginCurrentSoftwareInstance
RequestComputerPartitionNotReadyResponse
Tic
SlapLogout
SlapLoginCurrentSoftwareInstance
RequestComputerPartition
Tic
SlapLogout
LoginDefaultUser
CheckSoftwareInstanceAndRelatedComputerPartitionNoPackingListCheck
CheckRequestedSoftwareInstanceAndRelatedComputerPartition
Logout
LoginDefaultUser
SetCurrentSoftwareInstanceRequested
SetSelectedComputerPartition
SelectCurrentlyUsedSalePackingListUid
Logout
SlapLoginCurrentSoftwareInstance
CheckRequestedComputerPartitionCleanParameterList
Logout
# Try to: from C request B and prove that it raises
SelectRequestedReferenceB
LoginDefaultUser # login as superuser in order to work in erp5
DirectRequestComputerPartitionRaisesCyclicSoftwareTree
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
########################################
# Software Instance graph helpers
########################################
......
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