Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
slapos.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Ophélie Gagnard
slapos.core
Commits
88bdb2d7
Commit
88bdb2d7
authored
Apr 01, 2022
by
Rafael Monnerat
Browse files
Options
Browse Files
Download
Plain Diff
Slaptool Major clean up
See merge request
nexedi/slapos.core!368
parents
839ac0ef
5804e551
Changes
44
Hide whitespace changes
Inline
Side-by-side
Showing
44 changed files
with
2385 additions
and
847 deletions
+2385
-847
master/bt5/slapos_cloud/DocumentTemplateItem/portal_components/document.erp5.SoftwareInstance.py
...eItem/portal_components/document.erp5.SoftwareInstance.py
+207
-15
master/bt5/slapos_cloud/DocumentTemplateItem/portal_components/document.erp5.SoftwareInstance.xml
...Item/portal_components/document.erp5.SoftwareInstance.xml
+50
-19
master/bt5/slapos_cloud/MixinTemplateItem/portal_components/mixin.erp5.SlapOSCacheMixin.py
...lateItem/portal_components/mixin.erp5.SlapOSCacheMixin.py
+21
-3
master/bt5/slapos_cloud/MixinTemplateItem/portal_components/mixin.erp5.SlapOSComputeNodeMixin.py
...em/portal_components/mixin.erp5.SlapOSComputeNodeMixin.py
+349
-0
master/bt5/slapos_cloud/MixinTemplateItem/portal_components/mixin.erp5.SlapOSComputeNodeMixin.xml
...m/portal_components/mixin.erp5.SlapOSComputeNodeMixin.xml
+167
-0
master/bt5/slapos_cloud/MixinTemplateItem/portal_components/mixin.erp5.SlapOSComputePartitionMixin.py
...rtal_components/mixin.erp5.SlapOSComputePartitionMixin.py
+125
-0
master/bt5/slapos_cloud/MixinTemplateItem/portal_components/mixin.erp5.SlapOSComputePartitionMixin.xml
...tal_components/mixin.erp5.SlapOSComputePartitionMixin.xml
+133
-0
master/bt5/slapos_cloud/PathTemplateItem/portal_caches/compute_node_information_cache_factory.xml
.../portal_caches/compute_node_information_cache_factory.xml
+0
-0
master/bt5/slapos_cloud/PathTemplateItem/portal_caches/compute_node_information_cache_factory/persistent_cache_plugin.xml
...ode_information_cache_factory/persistent_cache_plugin.xml
+0
-0
master/bt5/slapos_cloud/PortalTypeTypeMixinTemplateItem/type_mixin.xml
...apos_cloud/PortalTypeTypeMixinTemplateItem/type_mixin.xml
+2
-0
master/bt5/slapos_cloud/TestTemplateItem/portal_components/test.erp5.testSlapOSCloud.py
...mplateItem/portal_components/test.erp5.testSlapOSCloud.py
+659
-0
master/bt5/slapos_cloud/TestTemplateItem/portal_components/test.erp5.testSlapOSCloud.xml
...plateItem/portal_components/test.erp5.testSlapOSCloud.xml
+133
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/compute_node_slap_interface_workflow/script_ComputeNode_reportBang.py
..._slap_interface_workflow/script_ComputeNode_reportBang.py
+2
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/compute_node_slap_interface_workflow/script_ComputeNode_reportBang.xml
...slap_interface_workflow/script_ComputeNode_reportBang.xml
+6
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_bangInstanceTree.py
...ace_workflow/script_RequestedInstance_bangInstanceTree.py
+3
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_bangInstanceTree.xml
...ce_workflow/script_RequestedInstance_bangInstanceTree.xml
+6
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_generateCertificate.py
..._workflow/script_RequestedInstance_generateCertificate.py
+19
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_generateCertificate.xml
...workflow/script_RequestedInstance_generateCertificate.xml
+78
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_rename.py
...lap_interface_workflow/script_RequestedInstance_rename.py
+8
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_rename.xml
...ap_interface_workflow/script_RequestedInstance_rename.xml
+6
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_revokeCertificate.py
...ce_workflow/script_RequestedInstance_revokeCertificate.py
+19
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_revokeCertificate.xml
...e_workflow/script_RequestedInstance_revokeCertificate.xml
+78
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_updateConnectionInformation.py
...w/script_RequestedInstance_updateConnectionInformation.py
+2
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_updateConnectionInformation.xml
.../script_RequestedInstance_updateConnectionInformation.xml
+6
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequesterInstance_request.py
...ap_interface_workflow/script_RequesterInstance_request.py
+2
-7
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequesterInstance_request.xml
...p_interface_workflow/script_RequesterInstance_request.xml
+6
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/state_destroy_requested.xml
...tance_slap_interface_workflow/state_destroy_requested.xml
+2
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/state_draft.xml
...workflow/instance_slap_interface_workflow/state_draft.xml
+2
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/state_start_requested.xml
...nstance_slap_interface_workflow/state_start_requested.xml
+2
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/state_stop_requested.xml
...instance_slap_interface_workflow/state_stop_requested.xml
+2
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/transition_generate_certificate.xml
...ap_interface_workflow/transition_generate_certificate.xml
+67
-0
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/transition_revoke_certificate.xml
...slap_interface_workflow/transition_revoke_certificate.xml
+67
-0
master/bt5/slapos_cloud/bt/template_action_path_list
master/bt5/slapos_cloud/bt/template_action_path_list
+5
-5
master/bt5/slapos_cloud/bt/template_mixin_id_list
master/bt5/slapos_cloud/bt/template_mixin_id_list
+3
-1
master/bt5/slapos_cloud/bt/template_path_list
master/bt5/slapos_cloud/bt/template_path_list
+2
-0
master/bt5/slapos_cloud/bt/template_portal_type_base_category_list
...5/slapos_cloud/bt/template_portal_type_base_category_list
+2
-2
master/bt5/slapos_cloud/bt/template_portal_type_type_mixin_list
.../bt5/slapos_cloud/bt/template_portal_type_type_mixin_list
+2
-0
master/bt5/slapos_cloud/bt/template_test_id_list
master/bt5/slapos_cloud/bt/template_test_id_list
+2
-1
master/bt5/slapos_crm/TestTemplateItem/portal_components/test.erp5.testSlapOSCRMSkins.py
...ateItem/portal_components/test.erp5.testSlapOSCRMSkins.py
+12
-12
master/bt5/slapos_slap_tool/ExtensionTemplateItem/portal_components/extension.erp5.SlapOSSlapTool.py
...teItem/portal_components/extension.erp5.SlapOSSlapTool.py
+6
-7
master/bt5/slapos_slap_tool/TestTemplateItem/portal_components/test.erp5.testSlapOSSlapTool.py
...ateItem/portal_components/test.erp5.testSlapOSSlapTool.py
+19
-91
master/bt5/slapos_slap_tool/ToolComponentTemplateItem/portal_components/tool.erp5.SlapTool.py
...onentTemplateItem/portal_components/tool.erp5.SlapTool.py
+100
-681
master/bt5/slapos_slap_tool/bt/template_keep_path_list
master/bt5/slapos_slap_tool/bt/template_keep_path_list
+3
-1
master/bt5/slapos_slap_tool/bt/template_path_list
master/bt5/slapos_slap_tool/bt/template_path_list
+0
-2
No files found.
master/bt5/slapos_cloud/DocumentTemplateItem/portal_components/document.erp5.SoftwareInstance.py
View file @
88bdb2d7
...
...
@@ -31,6 +31,32 @@ from erp5.component.document.Item import Item
from
lxml
import
etree
import
collections
from
AccessControl
import
Unauthorized
from
AccessControl.Permissions
import
access_contents_information
from
AccessControl
import
getSecurityManager
from
Products.ERP5Type.UnrestrictedMethod
import
UnrestrictedMethod
from
zLOG
import
LOG
,
INFO
try
:
from
slapos.slap.slap
import
\
SoftwareInstance
as
SlapSoftwareInstance
from
slapos.util
import
xml2dict
,
loads
except
ImportError
:
def
xml2dict
(
dictionary
):
raise
ImportError
def
loads
(
*
args
):
raise
ImportError
class
SlapSoftwareInstance
:
def
__init__
(
self
):
raise
ImportError
def
_assertACI
(
document
):
sm
=
getSecurityManager
()
if
sm
.
checkPermission
(
access_contents_information
,
document
):
return
document
raise
Unauthorized
(
'User %r has no access to %r'
%
(
sm
.
getUser
(),
document
))
class
DisconnectedSoftwareTree
(
Exception
):
pass
...
...
@@ -52,21 +78,18 @@ class SoftwareInstance(Item):
def
_getXmlAsDict
(
self
,
xml
):
result_dict
=
{}
if
xml
is
None
or
xml
==
''
:
return
result_dict
tree
=
etree
.
fromstring
(
xml
)
for
element
in
tree
.
findall
(
'parameter'
):
key
=
element
.
get
(
'id'
).
encode
(
"UTF-8"
)
value
=
result_dict
.
get
(
key
,
None
)
if
value
is
not
None
:
value
=
(
value
+
' '
+
element
.
text
)
else
:
value
=
element
.
text
if
value
is
not
None
:
value
=
value
.
encode
(
"UTF-8"
)
result_dict
[
key
]
=
value
if
xml
:
tree
=
etree
.
fromstring
(
xml
)
for
element
in
tree
.
iterfind
(
'parameter'
):
key
=
element
.
get
(
'id'
).
encode
(
"UTF-8"
)
value
=
result_dict
.
get
(
key
,
None
)
if
value
is
not
None
:
value
=
(
value
+
' '
+
element
.
text
)
else
:
value
=
element
.
text
if
value
is
not
None
:
value
=
value
.
encode
(
"UTF-8"
)
result_dict
[
key
]
=
value
return
result_dict
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
...
...
@@ -127,3 +150,172 @@ class SoftwareInstance(Item):
if
size
!=
len
(
visited
)
+
1
:
raise
DisconnectedSoftwareTree
return
True
def
_instanceXmlToDict
(
self
,
xml
):
result_dict
=
{}
try
:
result_dict
=
xml2dict
(
xml
)
except
(
etree
.
XMLSchemaError
,
etree
.
XMLSchemaParseError
,
# pylint: disable=catching-non-exception
etree
.
XMLSchemaValidateError
,
etree
.
XMLSyntaxError
):
# pylint: disable=catching-non-exception
LOG
(
'SoftwareInstance'
,
INFO
,
'Issue during parsing xml:'
,
error
=
True
)
return
result_dict
def
_asSoftwareInstance
(
self
):
parameter_dict
=
self
.
_asParameterDict
()
requested_state
=
self
.
getSlapState
()
if
requested_state
==
"stop_requested"
:
state
=
'stopped'
elif
requested_state
==
"start_requested"
:
state
=
'started'
elif
requested_state
==
"destroy_requested"
:
state
=
'destroyed'
else
:
raise
ValueError
(
"Unknown slap state : %s"
%
requested_state
)
# software instance has to define an xml parameter
xml
=
self
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'xml'
))
connection_xml
=
self
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'connection_xml'
))
filter_xml
=
self
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'filter_xml'
))
instance_guid
=
parameter_dict
.
pop
(
'instance_guid'
)
software_instance
=
SlapSoftwareInstance
(
**
parameter_dict
)
software_instance
.
_parameter_dict
=
xml
software_instance
.
_connection_dict
=
connection_xml
software_instance
.
_filter_dict
=
filter_xml
software_instance
.
_requested_state
=
state
software_instance
.
_instance_guid
=
instance_guid
return
software_instance
@
UnrestrictedMethod
def
_asParameterDict
(
self
,
shared_instance_sql_list
=
None
):
portal
=
self
.
getPortalObject
()
compute_partition
=
self
.
getAggregateValue
(
portal_type
=
"Compute Partition"
)
if
compute_partition
is
None
:
raise
ValueError
(
"Instance isn't allocated to call _asParamterDict"
)
timestamp
=
int
(
compute_partition
.
getModificationDate
())
newtimestamp
=
int
(
self
.
getBangTimestamp
(
int
(
self
.
getModificationDate
())))
if
(
newtimestamp
>
timestamp
):
timestamp
=
newtimestamp
instance_tree
=
self
.
getSpecialiseValue
()
ip_list
=
[]
full_ip_list
=
[]
for
internet_protocol_address
in
compute_partition
.
contentValues
(
portal_type
=
'Internet Protocol Address'
):
# XXX - There is new values, and we must keep compatibility
address_tuple
=
(
internet_protocol_address
.
getNetworkInterface
(
''
).
decode
(
"UTF-8"
),
internet_protocol_address
.
getIpAddress
().
decode
(
"UTF-8"
))
if
internet_protocol_address
.
getGatewayIpAddress
(
''
)
and
\
internet_protocol_address
.
getNetmask
(
''
):
address_tuple
=
address_tuple
+
(
internet_protocol_address
.
getGatewayIpAddress
().
decode
(
"UTF-8"
),
internet_protocol_address
.
getNetmask
().
decode
(
"UTF-8"
),
internet_protocol_address
.
getNetworkAddress
(
''
).
decode
(
"UTF-8"
))
full_ip_list
.
append
(
address_tuple
)
else
:
ip_list
.
append
(
address_tuple
)
shared_instance_list
=
[]
if
(
self
.
getPortalType
()
==
"Software Instance"
):
append
=
shared_instance_list
.
append
if
shared_instance_sql_list
is
None
:
shared_instance_sql_list
=
portal
.
portal_catalog
.
unrestrictedSearchResults
(
default_aggregate_uid
=
compute_partition
.
getUid
(),
portal_type
=
'Slave Instance'
,
validation_state
=
"validated"
,
**
{
"slapos_item.slap_state"
:
"start_requested"
}
)
for
shared_instance
in
shared_instance_sql_list
:
shared_instance
=
_assertACI
(
shared_instance
.
getObject
())
# XXX Use catalog to filter more efficiently
if
shared_instance
.
getSlapState
()
==
"start_requested"
:
newtimestamp
=
int
(
shared_instance
.
getBangTimestamp
(
int
(
shared_instance
.
getModificationDate
())))
append
({
'slave_title'
:
shared_instance
.
getTitle
().
decode
(
"UTF-8"
),
'slap_software_type'
:
\
shared_instance
.
getSourceReference
().
decode
(
"UTF-8"
),
'slave_reference'
:
shared_instance
.
getReference
().
decode
(
"UTF-8"
),
'timestamp'
:
newtimestamp
,
'xml'
:
shared_instance
.
getTextContent
(),
'connection_xml'
:
shared_instance
.
getConnectionXml
(),
})
if
(
newtimestamp
>
timestamp
):
timestamp
=
newtimestamp
return
{
'instance_guid'
:
self
.
getReference
().
decode
(
"UTF-8"
),
'instance_title'
:
self
.
getTitle
().
decode
(
"UTF-8"
),
'root_instance_title'
:
instance_tree
.
getTitle
().
decode
(
"UTF-8"
),
'root_instance_short_title'
:
instance_tree
.
getShortTitle
().
decode
(
"UTF-8"
),
'xml'
:
self
.
getTextContent
(),
'connection_xml'
:
self
.
getConnectionXml
(),
'filter_xml'
:
self
.
getSlaXml
(),
'slap_computer_id'
:
\
compute_partition
.
getParentValue
().
getReference
().
decode
(
"UTF-8"
),
'slap_computer_partition_id'
:
\
compute_partition
.
getReference
().
decode
(
"UTF-8"
),
'slap_software_type'
:
\
self
.
getSourceReference
().
decode
(
"UTF-8"
),
'slap_software_release_url'
:
\
self
.
getUrlString
().
decode
(
"UTF-8"
),
'slave_instance_list'
:
shared_instance_list
,
'ip_list'
:
ip_list
,
'full_ip_list'
:
full_ip_list
,
'timestamp'
:
"%i"
%
timestamp
,
}
@
UnrestrictedMethod
def
_getInstanceTreeIpList
(
self
):
if
self
.
getSlapState
()
==
'destroy_requested'
:
return
[]
# Search instance tree
instance_tree
=
self
.
getSpecialiseValue
()
while
instance_tree
and
instance_tree
.
getPortalType
()
!=
"Instance Tree"
:
instance_tree
=
instance_tree
.
getSpecialiseValue
()
ip_address_list
=
[]
for
instance
in
instance_tree
.
getSpecialiseRelatedValueList
(
portal_type
=
"Software Instance"
):
compute_partition
=
instance
.
getAggregateValue
(
portal_type
=
"Compute Partition"
)
if
not
compute_partition
:
continue
for
internet_protocol_address
in
compute_partition
.
contentValues
(
portal_type
=
'Internet Protocol Address'
):
ip_address_list
.
append
(
(
internet_protocol_address
.
getNetworkInterface
(
''
).
decode
(
"UTF-8"
),
internet_protocol_address
.
getIpAddress
().
decode
(
"UTF-8"
))
)
return
ip_address_list
def
_updateSucessorList
(
self
,
instance_reference_xml
):
"""
Update Software Instance successor list to match the given list. If one
instance was not requested by this compute partition, it should be removed
in the successor_list of this instance.
Once the link is removed, this instance will be trashed by Garbage Collect!
instance_reference_xml contain list of title of sub-instances requested by
this instance.
"""
cache_reference
=
'%s-PREDLIST'
%
self
.
getReference
()
if
not
self
.
isLastData
(
cache_reference
,
instance_reference_xml
):
instance_reference_list
=
loads
(
instance_reference_xml
)
current_successor_list
=
self
.
getSuccessorValueList
(
portal_type
=
[
'Software Instance'
,
'Slave Instance'
])
current_successor_title_list
=
[
i
.
getTitle
()
for
i
in
current_successor_list
]
# If there are items to remove
if
list
(
set
(
current_successor_title_list
).
difference
(
instance_reference_list
))
!=
[]:
successor_list
=
[
instance
.
getRelativeUrl
()
for
instance
in
current_successor_list
if
instance
.
getTitle
()
in
instance_reference_list
]
LOG
(
'SoftwareInstance'
,
INFO
,
'%s : Updating successor list to %s'
%
(
self
.
getReference
(),
successor_list
),
error
=
False
)
self
.
edit
(
successor_list
=
successor_list
,
comment
=
'successor_list edited to unlink non commited instances'
)
self
.
setLastData
(
instance_reference_xml
,
key
=
cache_reference
)
\ No newline at end of file
master/bt5/slapos_cloud/DocumentTemplateItem/portal_components/document.erp5.SoftwareInstance.xml
View file @
88bdb2d7
...
...
@@ -6,10 +6,22 @@
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_recorded_property_dict
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAI=
</string>
</persistent>
</value>
</item>
<item>
<key>
<string>
default_reference
</string>
</key>
<value>
<string>
SoftwareInstance
</string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
document.erp5.SoftwareInstance
</string>
</value>
...
...
@@ -43,13 +55,28 @@
<item>
<key>
<string>
workflow_history
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAA
I
=
</string>
</persistent>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAA
M
=
</string>
</persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"2"
aka=
"AAAAAAAAAAI="
>
<pickle>
<global
name=
"PersistentMapping"
module=
"Persistence.mapping"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
data
</string>
</key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"3"
aka=
"AAAAAAAAAAM="
>
<pickle>
<global
name=
"PersistentMapping"
module=
"Persistence.mapping"
/>
</pickle>
...
...
@@ -62,7 +89,7 @@
<item>
<key>
<string>
component_validation_workflow
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAA
M
=
</string>
</persistent>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAA
Q
=
</string>
</persistent>
</value>
</item>
</dictionary>
...
...
@@ -71,26 +98,30 @@
</dictionary>
</pickle>
</record>
<record
id=
"
3"
aka=
"AAAAAAAAAAM
="
>
<record
id=
"
4"
aka=
"AAAAAAAAAAQ
="
>
<pickle>
<global
name=
"WorkflowHistoryList"
module=
"Products.ERP5Type.
patches.WorkflowTool
"
/>
<global
name=
"WorkflowHistoryList"
module=
"Products.ERP5Type.
Workflow
"
/>
</pickle>
<pickle>
<tuple>
<none/>
<list>
<dictionary>
<item>
<key>
<string>
action
</string>
</key>
<value>
<string>
validate
</string>
</value>
</item>
<item>
<key>
<string>
validation_state
</string>
</key>
<value>
<string>
validated
</string>
</value>
</item>
</dictionary>
</list>
</tuple>
<dictionary>
<item>
<key>
<string>
_log
</string>
</key>
<value>
<list>
<dictionary>
<item>
<key>
<string>
action
</string>
</key>
<value>
<string>
validate
</string>
</value>
</item>
<item>
<key>
<string>
validation_state
</string>
</key>
<value>
<string>
validated
</string>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
master/bt5/slapos_cloud/MixinTemplateItem/portal_components/mixin.erp5.SlapOSCacheMixin.py
View file @
88bdb2d7
...
...
@@ -35,6 +35,10 @@ from Products.ERP5Type.Cache import DEFAULT_CACHE_SCOPE
import
json
ACCESS
=
"#access"
ERROR
=
"#error"
BUILDING
=
"#building"
class
SlapOSCacheMixin
:
# Declarative security
...
...
@@ -93,7 +97,16 @@ class SlapOSCacheMixin:
return
data_dict
def
setAccessStatus
(
self
,
text
,
state
=
""
):
def
setAccessStatus
(
self
,
text
,
state
=
""
,
reindex
=
0
):
return
self
.
_setAccessStatus
(
"%s %s"
%
(
ACCESS
,
text
),
state
,
reindex
)
def
setErrorStatus
(
self
,
text
,
state
=
""
,
reindex
=
0
):
return
self
.
_setAccessStatus
(
"%s %s"
%
(
ERROR
,
text
),
state
,
reindex
)
def
setBuildingStatus
(
self
,
text
,
state
=
""
,
reindex
=
0
):
return
self
.
_setAccessStatus
(
"%s %s"
%
(
BUILDING
,
text
),
state
,
reindex
)
def
_setAccessStatus
(
self
,
text
,
state
=
""
,
reindex
=
0
):
user_reference
=
self
.
getPortalObject
().
portal_membership
.
getAuthenticatedMember
()
\
.
getUserName
()
...
...
@@ -121,6 +134,9 @@ class SlapOSCacheMixin:
cache_duration
=
self
.
_getAccessStatusCacheFactory
().
cache_duration
self
.
_getAccessStatusPlugin
().
set
(
self
.
_getAccessStatusCacheKey
(),
DEFAULT_CACHE_SCOPE
,
value
,
cache_duration
=
cache_duration
)
if
status_changed
and
reindex
:
self
.
reindexObject
()
return
status_changed
def
getTextAccessStatus
(
self
):
...
...
@@ -134,7 +150,6 @@ class SlapOSCacheMixin:
date
=
DateTime
(
data_dict
[
'created_at'
])
return
date
.
strftime
(
'%Y/%m/%d %H:%M'
)
#####################
# SlapOS Last Data
#####################
...
...
@@ -165,4 +180,7 @@ class SlapOSCacheMixin:
entry
=
None
else
:
entry
=
entry
.
getValue
()
return
entry
\ No newline at end of file
return
entry
def
isLastData
(
self
,
key
=
None
,
value
=
None
):
return
self
.
getLastData
(
key
)
==
value
\ No newline at end of file
master/bt5/slapos_cloud/MixinTemplateItem/portal_components/mixin.erp5.SlapOSComputeNodeMixin.py
0 → 100644
View file @
88bdb2d7
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010-2022 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from
Products.ERP5Type.Cache
import
DEFAULT_CACHE_SCOPE
from
AccessControl
import
Unauthorized
from
AccessControl.Permissions
import
access_contents_information
from
AccessControl
import
getSecurityManager
from
Products.ERP5Type.UnrestrictedMethod
import
UnrestrictedMethod
from
Products.ERP5Type.tests.utils
import
DummyMailHostMixin
from
OFS.Traversable
import
NotFound
import
time
from
lxml
import
etree
from
zLOG
import
LOG
,
INFO
try
:
from
slapos.slap.slap
import
(
Computer
as
ComputeNode
,
ComputerPartition
as
SlapComputePartition
,
SoftwareRelease
)
from
slapos.util
import
xml2dict
,
dumps
except
ImportError
:
# Do no prevent instance from starting
# if libs are not installed
class
ComputeNode
:
def
__init__
(
self
):
raise
ImportError
class
SlapComputePartition
:
def
__init__
(
self
):
raise
ImportError
class
SoftwareRelease
:
def
__init__
(
self
):
raise
ImportError
def
xml2dict
(
dictionary
):
raise
ImportError
def
dumps
(
*
args
):
raise
ImportError
def
_assertACI
(
document
):
sm
=
getSecurityManager
()
if
sm
.
checkPermission
(
access_contents_information
,
document
):
return
document
raise
Unauthorized
(
'User %r has no access to %r'
%
(
sm
.
getUser
(),
document
))
class
SlapOSComputeNodeMixin
(
object
):
def
_getCachePlugin
(
self
):
return
self
.
getPortalObject
().
portal_caches
\
.
getRamCacheRoot
().
get
(
'compute_node_information_cache_factory'
)
\
.
getCachePluginList
()[
0
]
@
UnrestrictedMethod
def
_getSoftwareReleaseValueList
(
self
):
"""Returns list of Software Releases documents for compute_node"""
portal
=
self
.
getPortalObject
()
software_release_list
=
[]
for
software_installation
in
portal
.
portal_catalog
.
unrestrictedSearchResults
(
portal_type
=
'Software Installation'
,
default_aggregate_uid
=
self
.
getUid
(),
validation_state
=
'validated'
,
):
software_installation
=
_assertACI
(
software_installation
.
getObject
())
software_release_response
=
SoftwareRelease
(
software_release
=
software_installation
.
getUrlString
().
decode
(
'UTF-8'
),
computer_guid
=
self
.
getReference
().
decode
(
'UTF-8'
))
if
software_installation
.
getSlapState
()
==
'destroy_requested'
:
software_release_response
.
_requested_state
=
'destroyed'
else
:
software_release_response
.
_requested_state
=
'available'
known_state
=
software_installation
.
getTextAccessStatus
()
if
known_state
.
startswith
(
"#access"
):
software_release_response
.
_known_state
=
'available'
elif
known_state
.
startswith
(
"#building"
):
software_release_response
.
_known_state
=
'building'
else
:
software_release_response
.
_known_state
=
'error'
software_release_list
.
append
(
software_release_response
)
return
software_release_list
def
_getCacheComputeNodeInformation
(
self
,
user
):
self
.
REQUEST
.
response
.
setHeader
(
'Content-Type'
,
'text/xml; charset=utf-8'
)
slap_compute_node
=
ComputeNode
(
self
.
getReference
().
decode
(
"UTF-8"
))
slap_compute_node
.
_computer_partition_list
=
[]
slap_compute_node
.
_software_release_list
=
self
.
_getSoftwareReleaseValueList
()
unrestrictedSearchResults
=
self
.
getPortalObject
().
portal_catalog
.
unrestrictedSearchResults
compute_partition_list
=
unrestrictedSearchResults
(
parent_uid
=
self
.
getUid
(),
validation_state
=
"validated"
,
portal_type
=
"Compute Partition"
)
self
.
_calculateSlapComputeNodeInformation
(
slap_compute_node
,
compute_partition_list
)
return
dumps
(
slap_compute_node
)
def
_activateFillComputeNodeInformationCache
(
self
,
user
):
tag
=
'compute_node_information_cache_fill_%s_%s'
%
(
self
.
getReference
(),
user
)
if
self
.
getPortalObject
().
portal_activities
.
countMessageWithTag
(
tag
)
==
0
:
self
.
activate
(
activity
=
'SQLQueue'
,
priority
=
2
,
tag
=
tag
).
_fillComputeNodeInformationCache
(
user
)
def
_fillComputeNodeInformationCache
(
self
,
user
):
key
=
'%s_%s'
%
(
self
.
getReference
(),
user
)
try
:
self
.
_getCachePlugin
().
set
(
key
,
DEFAULT_CACHE_SCOPE
,
dict
(
time
=
time
.
time
(),
refresh_etag
=
self
.
_calculateRefreshEtag
(),
data
=
self
.
_getCacheComputeNodeInformation
(
user
),
),
cache_duration
=
self
.
getPortalObject
().
portal_caches
\
.
getRamCacheRoot
().
get
(
'compute_node_information_cache_factory'
\
).
cache_duration
)
except
(
Unauthorized
,
IndexError
):
# XXX: Unauthorized hack. Race condition of not ready setup delivery which provides
# security information shall not make this method fail, as it will be
# called later anyway
# Note: IndexError ignored, as it happend in case if full reindex is
# called on site
pass
def
_calculateRefreshEtag
(
self
):
# check max indexation timestamp
# it is unlikely to get an empty catalog
last_indexed_entry
=
self
.
getPortalObject
().
portal_catalog
(
select_list
=
[
'indexation_timestamp'
],
portal_type
=
[
'Compute Node'
,
'Compute Partition'
,
'Software Instance'
,
'Slave Instance'
,
'Software Installation'
],
sort_on
=
[(
'indexation_timestamp'
,
'DESC'
)],
limit
=
1
,
)[
0
]
return
'%s_%s'
%
(
last_indexed_entry
.
uid
,
last_indexed_entry
.
indexation_timestamp
)
def
_isTestRun
(
self
):
if
self
.
REQUEST
.
get
(
'disable_isTestRun'
,
False
):
return
False
if
issubclass
(
self
.
getPortalObject
().
MailHost
.
__class__
,
DummyMailHostMixin
)
\
or
self
.
REQUEST
.
get
(
'test_list'
):
return
True
return
False
def
_getComputeNodeInformation
(
self
,
user
,
refresh_etag
):
portal
=
self
.
getPortalObject
()
user_document
=
_assertACI
(
portal
.
portal_catalog
.
unrestrictedGetResultValue
(
reference
=
user
,
portal_type
=
[
'Person'
,
'Compute Node'
,
'Software Instance'
]))
user_type
=
user_document
.
getPortalType
()
self
.
REQUEST
.
response
.
setHeader
(
'Content-Type'
,
'text/xml; charset=utf-8'
)
slap_compute_node
=
ComputeNode
(
self
.
getReference
().
decode
(
"UTF-8"
))
slap_compute_node
.
_computer_partition_list
=
[]
if
user_type
in
(
'Compute Node'
,
'Person'
):
if
not
self
.
_isTestRun
():
cache_plugin
=
self
.
_getCachePlugin
()
key
=
'%s_%s'
%
(
self
.
getReference
(),
user
)
try
:
entry
=
cache_plugin
.
get
(
key
,
DEFAULT_CACHE_SCOPE
)
except
KeyError
:
entry
=
None
if
entry
is
not
None
and
isinstance
(
entry
.
getValue
(),
dict
):
cached_dict
=
entry
.
getValue
()
cached_etag
=
cached_dict
.
get
(
'refresh_etag'
,
None
)
if
(
refresh_etag
!=
cached_etag
):
# Do not recalculate the compute_node information
# if nothing changed
self
.
_activateFillComputeNodeInformationCache
(
user
)
return
cached_dict
[
'data'
],
cached_etag
else
:
self
.
_activateFillComputeNodeInformationCache
(
user
)
self
.
REQUEST
.
response
.
setStatus
(
503
)
return
self
.
REQUEST
.
response
,
None
else
:
return
self
.
_getCacheComputeNodeInformation
(
user
),
None
else
:
slap_compute_node
.
_software_release_list
=
[]
if
user_type
==
'Software Instance'
:
compute_partition_list
=
self
.
contentValues
(
portal_type
=
"Compute Partition"
,
checked_permission
=
"View"
)
else
:
compute_partition_list
=
self
.
getPortalObject
().
portal_catalog
.
unrestrictedSearchResults
(
parent_uid
=
self
.
getUid
(),
validation_state
=
"validated"
,
portal_type
=
"Compute Partition"
)
self
.
_calculateSlapComputeNodeInformation
(
slap_compute_node
,
compute_partition_list
)
return
dumps
(
slap_compute_node
),
None
def
_calculateSlapComputeNodeInformation
(
self
,
slap_compute_node
,
compute_partition_list
):
if
len
(
compute_partition_list
)
==
0
:
return
unrestrictedSearchResults
=
self
.
getPortalObject
().
portal_catalog
.
unrestrictedSearchResults
compute_partition_uid_list
=
[
x
.
uid
for
x
in
compute_partition_list
]
grouped_software_instance_list
=
unrestrictedSearchResults
(
portal_type
=
"Software Instance"
,
default_aggregate_uid
=
compute_partition_uid_list
,
validation_state
=
"validated"
,
group_by_list
=
[
'default_aggregate_uid'
],
select_list
=
[
'default_aggregate_uid'
,
'count(*)'
]
)
slave_software_instance_list
=
unrestrictedSearchResults
(
default_aggregate_uid
=
compute_partition_uid_list
,
portal_type
=
'Slave Instance'
,
validation_state
=
"validated"
,
select_list
=
[
'default_aggregate_uid'
],
**
{
"slapos_item.slap_state"
:
"start_requested"
}
)
for
compute_partition
in
compute_partition_list
:
software_instance_list
=
[
x
for
x
in
grouped_software_instance_list
if
(
x
.
default_aggregate_uid
==
compute_partition
.
getUid
())]
if
(
len
(
software_instance_list
)
==
1
)
and
(
software_instance_list
[
0
][
'count(*)'
]
>
1
):
software_instance_list
=
software_instance_list
+
software_instance_list
slap_compute_node
.
_computer_partition_list
.
append
(
self
.
_getSlapPartitionByPackingList
(
_assertACI
(
compute_partition
.
getObject
()),
software_instance_list
,
[
x
for
x
in
slave_software_instance_list
if
(
x
.
default_aggregate_uid
==
compute_partition
.
getUid
())]
)
)
def
_instanceXmlToDict
(
self
,
xml
):
result_dict
=
{}
try
:
result_dict
=
xml2dict
(
xml
)
except
(
etree
.
XMLSchemaError
,
etree
.
XMLSchemaParseError
,
# pylint: disable=catching-non-exception
etree
.
XMLSchemaValidateError
,
etree
.
XMLSyntaxError
):
# pylint: disable=catching-non-exception
LOG
(
'SlapOSComputeNodeCacheMixin'
,
INFO
,
'Issue during parsing xml:'
,
error
=
True
)
return
result_dict
def
_getSlapPartitionByPackingList
(
self
,
compute_partition_document
,
software_instance_list
,
shared_instance_sql_list
):
compute_node
=
compute_partition_document
while
compute_node
.
getPortalType
()
!=
'Compute Node'
:
compute_node
=
compute_node
.
getParentValue
()
compute_node_id
=
compute_node
.
getReference
().
decode
(
"UTF-8"
)
slap_partition
=
SlapComputePartition
(
compute_node_id
,
compute_partition_document
.
getReference
().
decode
(
"UTF-8"
))
slap_partition
.
_software_release_document
=
None
slap_partition
.
_requested_state
=
'destroyed'
slap_partition
.
_need_modification
=
0
software_instance
=
None
if
compute_partition_document
.
getSlapState
()
==
'busy'
:
software_instance_count
=
len
(
software_instance_list
)
if
software_instance_count
==
1
:
software_instance
=
_assertACI
(
software_instance_list
[
0
].
getObject
())
elif
software_instance_count
>
1
:
# XXX do not prevent the system to work if one partition is broken
raise
NotImplementedError
,
"Too many instances linked to %s"
%
\
compute_partition_document
.
getRelativeUrl
()
if
software_instance
is
not
None
:
state
=
software_instance
.
getSlapState
()
if
state
==
"stop_requested"
:
slap_partition
.
_requested_state
=
'stopped'
if
state
==
"start_requested"
:
slap_partition
.
_requested_state
=
'started'
slap_partition
.
_access_status
=
software_instance
.
getTextAccessStatus
()
slap_partition
.
_software_release_document
=
SoftwareRelease
(
software_release
=
software_instance
.
getUrlString
().
decode
(
"UTF-8"
),
computer_guid
=
compute_node_id
)
slap_partition
.
_need_modification
=
1
parameter_dict
=
software_instance
.
_asParameterDict
(
shared_instance_sql_list
=
shared_instance_sql_list
)
# software instance has to define an xml parameter
slap_partition
.
_parameter_dict
=
self
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'xml'
))
slap_partition
.
_connection_dict
=
self
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'connection_xml'
))
slap_partition
.
_filter_dict
=
self
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'filter_xml'
))
slap_partition
.
_instance_guid
=
parameter_dict
.
pop
(
'instance_guid'
)
for
slave_instance_dict
in
parameter_dict
.
get
(
"slave_instance_list"
,
[]):
if
slave_instance_dict
.
has_key
(
"connection_xml"
):
slave_instance_dict
.
update
(
self
.
_instanceXmlToDict
(
slave_instance_dict
.
pop
(
"connection_xml"
)))
if
slave_instance_dict
.
has_key
(
"xml"
):
slave_instance_dict
.
update
(
self
.
_instanceXmlToDict
(
slave_instance_dict
.
pop
(
"xml"
)))
slap_partition
.
_parameter_dict
.
update
(
parameter_dict
)
return
slap_partition
def
_getSoftwareInstallationFromUrl
(
self
,
url
):
software_installation_list
=
self
.
getPortalObject
().
portal_catalog
.
unrestrictedSearchResults
(
portal_type
=
'Software Installation'
,
default_aggregate_uid
=
self
.
getUid
(),
validation_state
=
'validated'
,
limit
=
2
,
url_string
=
{
'query'
:
url
,
'key'
:
'ExactMatch'
},
)
l
=
len
(
software_installation_list
)
if
l
==
1
:
return
_assertACI
(
software_installation_list
[
0
].
getObject
())
elif
l
==
0
:
raise
NotFound
(
'No software release %r found on compute_node %r'
%
(
url
,
self
.
getReference
()))
else
:
raise
ValueError
(
'Wrong list of software releases on %r: %s'
%
(
self
.
getReference
(),
', '
.
join
([
q
.
getRelativeUrl
()
for
q
\
in
software_installation_list
])
))
master/bt5/slapos_cloud/MixinTemplateItem/portal_components/mixin.erp5.SlapOSComputeNodeMixin.xml
0 → 100644
View file @
88bdb2d7
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"Mixin Component"
module=
"erp5.portal_type"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_recorded_property_dict
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAI=
</string>
</persistent>
</value>
</item>
<item>
<key>
<string>
default_reference
</string>
</key>
<value>
<string>
SlapOSComputeNodeMixin
</string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
mixin.erp5.SlapOSComputeNodeMixin
</string>
</value>
</item>
<item>
<key>
<string>
portal_type
</string>
</key>
<value>
<string>
Mixin Component
</string>
</value>
</item>
<item>
<key>
<string>
sid
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
text_content_error_message
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
text_content_warning_message
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
version
</string>
</key>
<value>
<string>
erp5
</string>
</value>
</item>
<item>
<key>
<string>
workflow_history
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAM=
</string>
</persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"2"
aka=
"AAAAAAAAAAI="
>
<pickle>
<global
name=
"PersistentMapping"
module=
"Persistence.mapping"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
data
</string>
</key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"3"
aka=
"AAAAAAAAAAM="
>
<pickle>
<global
name=
"PersistentMapping"
module=
"Persistence.mapping"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
data
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
component_validation_workflow
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAQ=
</string>
</persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"4"
aka=
"AAAAAAAAAAQ="
>
<pickle>
<global
name=
"WorkflowHistoryList"
module=
"Products.ERP5Type.Workflow"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_log
</string>
</key>
<value>
<list>
<dictionary>
<item>
<key>
<string>
action
</string>
</key>
<value>
<string>
validate
</string>
</value>
</item>
<item>
<key>
<string>
error_message
</string>
</key>
<value>
<list>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAU=
</string>
</persistent>
</list>
</value>
</item>
<item>
<key>
<string>
validation_state
</string>
</key>
<value>
<string>
validated
</string>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"5"
aka=
"AAAAAAAAAAU="
>
<pickle>
<global
name=
"Message"
module=
"Products.ERP5Type.Message"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
default
</string>
</key>
<value>
<string>
Class ${reference} must be defined
</string>
</value>
</item>
<item>
<key>
<string>
domain
</string>
</key>
<value>
<string>
erp5_ui
</string>
</value>
</item>
<item>
<key>
<string>
mapping
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
reference
</string>
</key>
<value>
<string>
SlapOSComputeNodeCacheMixin
</string>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key>
<string>
message
</string>
</key>
<value>
<string>
Class ${reference} must be defined
</string>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
master/bt5/slapos_cloud/MixinTemplateItem/portal_components/mixin.erp5.SlapOSComputePartitionMixin.py
0 → 100644
View file @
88bdb2d7
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010-2022 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly advised to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from
AccessControl.Permissions
import
access_contents_information
from
AccessControl
import
getSecurityManager
from
AccessControl
import
Unauthorized
try
:
from
slapos.slap.slap
import
(
ComputerPartition
as
SlapComputePartition
,
SoftwareRelease
)
from
slapos.util
import
calculate_dict_hash
except
ImportError
:
# Do no prevent instance from starting
# if libs are not installed
class
SlapComputePartition
:
def
__init__
(
self
):
raise
ImportError
class
SoftwareRelease
:
def
__init__
(
self
):
raise
ImportError
def
calculate_dict_hash
(
*
args
):
raise
ImportError
def
_assertACI
(
document
):
sm
=
getSecurityManager
()
if
sm
.
checkPermission
(
access_contents_information
,
document
):
return
document
raise
Unauthorized
(
'User %r has no access to %r'
%
(
sm
.
getUser
(),
document
))
class
SlapOSComputePartitionMixin
(
object
):
def
_registerComputePartition
(
self
):
portal
=
self
.
getPortalObject
()
computer_reference
=
self
.
getParentValue
().
getReference
()
computer_partition_reference
=
self
.
getReference
()
slap_partition
=
SlapComputePartition
(
computer_reference
.
decode
(
"UTF-8"
),
computer_partition_reference
.
decode
(
"UTF-8"
))
slap_partition
.
_software_release_document
=
None
slap_partition
.
_requested_state
=
'destroyed'
slap_partition
.
_need_modification
=
0
software_instance
=
None
if
self
.
getSlapState
()
==
'busy'
:
software_instance_list
=
portal
.
portal_catalog
.
unrestrictedSearchResults
(
portal_type
=
"Software Instance"
,
default_aggregate_uid
=
self
.
getUid
(),
validation_state
=
"validated"
,
limit
=
2
,
)
software_instance_count
=
len
(
software_instance_list
)
if
software_instance_count
==
1
:
software_instance
=
_assertACI
(
software_instance_list
[
0
].
getObject
())
elif
software_instance_count
>
1
:
# XXX do not prevent the system to work if one partition is broken
raise
NotImplementedError
,
"Too many instances %s linked to %s"
%
\
([
x
.
path
for
x
in
software_instance_list
],
self
.
getRelativeUrl
())
if
software_instance
is
not
None
:
# trick client side, that data has been synchronised already for given
# document
slap_partition
.
_synced
=
True
state
=
software_instance
.
getSlapState
()
if
state
==
"stop_requested"
:
slap_partition
.
_requested_state
=
'stopped'
if
state
==
"start_requested"
:
slap_partition
.
_requested_state
=
'started'
slap_partition
.
_software_release_document
=
SoftwareRelease
(
software_release
=
software_instance
.
getUrlString
().
decode
(
"UTF-8"
),
computer_guid
=
computer_reference
.
decode
(
"UTF-8"
))
slap_partition
.
_need_modification
=
1
parameter_dict
=
software_instance
.
_asParameterDict
()
# software instance has to define an xml parameter
slap_partition
.
_parameter_dict
=
software_instance
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'xml'
))
slap_partition
.
_connection_dict
=
software_instance
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'connection_xml'
))
slap_partition
.
_filter_dict
=
software_instance
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'filter_xml'
))
slap_partition
.
_instance_guid
=
parameter_dict
.
pop
(
'instance_guid'
)
for
slave_instance_dict
in
parameter_dict
.
get
(
"slave_instance_list"
,
[]):
if
slave_instance_dict
.
has_key
(
"connection_xml"
):
connection_dict
=
software_instance
.
_instanceXmlToDict
(
slave_instance_dict
.
pop
(
"connection_xml"
))
slave_instance_dict
.
update
(
connection_dict
)
slave_instance_dict
[
'connection-parameter-hash'
]
=
\
calculate_dict_hash
(
connection_dict
)
if
slave_instance_dict
.
has_key
(
"xml"
):
slave_instance_dict
.
update
(
software_instance
.
_instanceXmlToDict
(
slave_instance_dict
.
pop
(
"xml"
)))
slap_partition
.
_parameter_dict
.
update
(
parameter_dict
)
return
slap_partition
master/bt5/slapos_cloud/MixinTemplateItem/portal_components/mixin.erp5.SlapOSComputePartitionMixin.xml
0 → 100644
View file @
88bdb2d7
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"Mixin Component"
module=
"erp5.portal_type"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_recorded_property_dict
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAI=
</string>
</persistent>
</value>
</item>
<item>
<key>
<string>
default_reference
</string>
</key>
<value>
<string>
SlapOSComputePartitionMixin
</string>
</value>
</item>
<item>
<key>
<string>
default_source_reference
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
mixin.erp5.SlapOSComputePartitionMixin
</string>
</value>
</item>
<item>
<key>
<string>
portal_type
</string>
</key>
<value>
<string>
Mixin Component
</string>
</value>
</item>
<item>
<key>
<string>
sid
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
text_content_error_message
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
text_content_warning_message
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
version
</string>
</key>
<value>
<string>
erp5
</string>
</value>
</item>
<item>
<key>
<string>
workflow_history
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAM=
</string>
</persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"2"
aka=
"AAAAAAAAAAI="
>
<pickle>
<global
name=
"PersistentMapping"
module=
"Persistence.mapping"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
data
</string>
</key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"3"
aka=
"AAAAAAAAAAM="
>
<pickle>
<global
name=
"PersistentMapping"
module=
"Persistence.mapping"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
data
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
component_validation_workflow
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAQ=
</string>
</persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"4"
aka=
"AAAAAAAAAAQ="
>
<pickle>
<global
name=
"WorkflowHistoryList"
module=
"Products.ERP5Type.Workflow"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_log
</string>
</key>
<value>
<list>
<dictionary>
<item>
<key>
<string>
action
</string>
</key>
<value>
<string>
validate
</string>
</value>
</item>
<item>
<key>
<string>
validation_state
</string>
</key>
<value>
<string>
validated
</string>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
master/bt5/slapos_
slap_tool
/PathTemplateItem/portal_caches/compute_node_information_cache_factory.xml
→
master/bt5/slapos_
cloud
/PathTemplateItem/portal_caches/compute_node_information_cache_factory.xml
View file @
88bdb2d7
File moved
master/bt5/slapos_
slap_tool
/PathTemplateItem/portal_caches/compute_node_information_cache_factory/persistent_cache_plugin.xml
→
master/bt5/slapos_
cloud
/PathTemplateItem/portal_caches/compute_node_information_cache_factory/persistent_cache_plugin.xml
View file @
88bdb2d7
File moved
master/bt5/slapos_cloud/PortalTypeTypeMixinTemplateItem/type_mixin.xml
View file @
88bdb2d7
<type_mixin>
<portal_type
id=
"Compute Node"
>
<item>
SlapOSCacheMixin
</item>
<item>
SlapOSComputeNodeMixin
</item>
</portal_type>
<portal_type
id=
"Compute Partition"
>
<item>
SlapOSCacheMixin
</item>
<item>
SlapOSComputePartitionMixin
</item>
</portal_type>
<portal_type
id=
"Person"
>
<item>
SlapOSCacheMixin
</item>
...
...
master/bt5/slapos_cloud/TestTemplateItem/portal_components/test.erp5.testSlapOSCloud.py
0 → 100644
View file @
88bdb2d7
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2022 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from
erp5.component.test.SlapOSTestCaseMixin
import
SlapOSTestCaseMixin
from
DateTime
import
DateTime
from
App.Common
import
rfc1123_date
import
json
import
hashlib
from
binascii
import
hexlify
def
hashData
(
data
):
return
hexlify
(
hashlib
.
sha1
(
data
).
digest
())
class
TestSlapOSCloudSlapOSCacheMixin
(
SlapOSTestCaseMixin
):
def
afterSetUp
(
self
):
SlapOSTestCaseMixin
.
afterSetUp
(
self
)
self
.
pinDateTime
(
DateTime
())
self
.
_makeComputeNode
()
self
.
_makeComplexComputeNode
(
with_slave
=
True
)
self
.
tic
()
def
beforeTearDown
(
self
):
self
.
unpinDateTime
()
self
.
_cleaupREQUEST
()
def
test_LastData
(
self
):
value
=
"XXX"
self
.
assertEqual
(
None
,
self
.
compute_node
.
getLastData
())
self
.
compute_node
.
setLastData
(
value
)
self
.
assertEqual
(
value
,
self
.
compute_node
.
getLastData
())
key
=
"OI"
value_key
=
"ABC"
self
.
assertEqual
(
None
,
self
.
compute_node
.
getLastData
(
key
))
self
.
compute_node
.
setLastData
(
value_key
,
key
=
key
)
self
.
assertEqual
(
value_key
,
self
.
compute_node
.
getLastData
(
key
))
def
test_getAccessStatus_no_data
(
self
):
since
=
rfc1123_date
(
DateTime
())
created_at
=
since
def
getBaseExpectedDict
(
doc
):
return
{
"user"
:
"SlapOS Master"
,
'created_at'
:
'%s'
%
created_at
,
'since'
:
'%s'
%
since
,
'state'
:
""
,
"text"
:
"#error no data found for %s"
%
doc
.
getReference
(),
"no_data"
:
1
}
# Check Compute Node
self
.
assertEqual
(
self
.
compute_node
.
_getCachedAccessInfo
(),
None
)
self
.
assertEqual
(
self
.
compute_node
.
getAccessStatus
(),
getBaseExpectedDict
(
self
.
compute_node
))
# Check Software Installation
installation
=
self
.
start_requested_software_installation
self
.
assertEqual
(
installation
.
_getCachedAccessInfo
(),
None
)
self
.
assertEqual
(
installation
.
getAccessStatus
(),
getBaseExpectedDict
(
installation
))
partition
=
self
.
compute_node
.
partition1
self
.
assertEqual
(
partition
.
_getCachedAccessInfo
(),
None
)
self
.
assertEqual
(
partition
.
getAccessStatus
(),
getBaseExpectedDict
(
partition
))
instance
=
self
.
start_requested_software_instance
self
.
assertEqual
(
instance
.
_getCachedAccessInfo
(),
None
)
self
.
assertEqual
(
instance
.
getAccessStatus
(),
getBaseExpectedDict
(
instance
))
def
test_setAccessStatus
(
self
):
since
=
rfc1123_date
(
DateTime
())
created_at
=
since
def
getExpectedCacheDict
(
doc
):
return
json
.
dumps
({
"user"
:
"ERP5TypeTestCase"
,
'created_at'
:
'%s'
%
created_at
,
'since'
:
'%s'
%
since
,
'state'
:
""
,
"text"
:
"#access TEST123 %s"
%
doc
.
getUid
()
})
def
getBaseExpectedDict
(
doc
):
return
{
"user"
:
"ERP5TypeTestCase"
,
'created_at'
:
'%s'
%
created_at
,
u'since'
:
u'%s'
%
since
,
u'state'
:
u""
,
u"text"
:
u"#access TEST123 %s"
%
doc
.
getUid
(),
'no_data_since_15_minutes'
:
0
,
'no_data_since_5_minutes'
:
0
}
# Check Compute Node
self
.
assertEqual
(
True
,
self
.
compute_node
.
setAccessStatus
(
"TEST123 %s"
%
self
.
compute_node
.
getUid
()))
self
.
assertEqual
(
self
.
compute_node
.
_getCachedAccessInfo
(),
getExpectedCacheDict
(
self
.
compute_node
))
self
.
assertEqual
(
self
.
compute_node
.
getAccessStatus
(),
getBaseExpectedDict
(
self
.
compute_node
))
self
.
assertEqual
(
False
,
self
.
compute_node
.
setAccessStatus
(
"TEST123 %s"
%
self
.
compute_node
.
getUid
()))
# Check Software Installation
installation
=
self
.
start_requested_software_installation
self
.
assertEqual
(
True
,
installation
.
setAccessStatus
(
"TEST123 %s"
%
installation
.
getUid
()))
self
.
assertEqual
(
installation
.
_getCachedAccessInfo
(),
getExpectedCacheDict
(
installation
))
self
.
assertEqual
(
installation
.
getAccessStatus
(),
getBaseExpectedDict
(
installation
))
self
.
assertEqual
(
False
,
installation
.
setAccessStatus
(
"TEST123 %s"
%
installation
.
getUid
()))
# Compute Partition
partition
=
self
.
compute_node
.
partition1
self
.
assertEqual
(
True
,
partition
.
setAccessStatus
(
"TEST123 %s"
%
partition
.
getUid
()))
self
.
assertEqual
(
partition
.
_getCachedAccessInfo
(),
getExpectedCacheDict
(
partition
))
self
.
assertEqual
(
partition
.
getAccessStatus
(),
getBaseExpectedDict
(
partition
))
self
.
assertEqual
(
False
,
partition
.
setAccessStatus
(
"TEST123 %s"
%
partition
.
getUid
()))
# Software Instance
instance
=
self
.
start_requested_software_instance
# This is already called from elsewhere, so it actually changed
self
.
assertEqual
(
True
,
instance
.
setAccessStatus
(
"TEST123 %s"
%
instance
.
getUid
()))
self
.
assertEqual
(
instance
.
_getCachedAccessInfo
(),
getExpectedCacheDict
(
instance
))
self
.
assertEqual
(
instance
.
getAccessStatus
(),
getBaseExpectedDict
(
instance
))
self
.
assertEqual
(
False
,
instance
.
setAccessStatus
(
"TEST123 %s"
%
instance
.
getUid
()))
def
test_setAccessStatus_reindex
(
self
):
since
=
rfc1123_date
(
DateTime
())
created_at
=
since
def
getExpectedCacheDict
(
doc
):
return
json
.
dumps
({
"user"
:
"ERP5TypeTestCase"
,
'created_at'
:
'%s'
%
created_at
,
'since'
:
'%s'
%
since
,
'state'
:
""
,
"text"
:
"#access TEST123 %s"
%
doc
.
getUid
()
})
def
getBaseExpectedDict
(
doc
):
return
{
"user"
:
"ERP5TypeTestCase"
,
'created_at'
:
'%s'
%
created_at
,
u'since'
:
u'%s'
%
since
,
u'state'
:
u""
,
u"text"
:
u"#access TEST123 %s"
%
doc
.
getUid
(),
'no_data_since_15_minutes'
:
0
,
'no_data_since_5_minutes'
:
0
}
self
.
tic
()
# Software Instance
instance
=
self
.
start_requested_software_instance
indexation_timestamp
=
self
.
portal
.
portal_catalog
(
uid
=
instance
.
getUid
(),
select_dict
=
{
"indexation_timestamp"
:
None
}
)[
0
].
indexation_timestamp
# This is already called from elsewhere, so it actually changed
self
.
assertEqual
(
True
,
instance
.
setAccessStatus
(
"TEST123 %s"
%
instance
.
getUid
()))
self
.
assertEqual
(
instance
.
_getCachedAccessInfo
(),
getExpectedCacheDict
(
instance
))
self
.
assertEqual
(
instance
.
getAccessStatus
(),
getBaseExpectedDict
(
instance
))
self
.
tic
()
new_indexation_timestamp
=
self
.
portal
.
portal_catalog
(
uid
=
instance
.
getUid
(),
select_dict
=
{
"indexation_timestamp"
:
None
}
)[
0
].
indexation_timestamp
self
.
assertEqual
(
new_indexation_timestamp
,
indexation_timestamp
)
self
.
assertEqual
(
False
,
instance
.
setAccessStatus
(
"TEST123 %s"
%
instance
.
getUid
()))
self
.
tic
()
new_indexation_timestamp
=
self
.
portal
.
portal_catalog
(
uid
=
instance
.
getUid
(),
select_dict
=
{
"indexation_timestamp"
:
None
}
)[
0
].
indexation_timestamp
self
.
assertEqual
(
new_indexation_timestamp
,
indexation_timestamp
)
self
.
assertEqual
(
False
,
instance
.
setAccessStatus
(
"TEST123 %s"
%
instance
.
getUid
(),
reindex
=
1
))
self
.
tic
()
new_indexation_timestamp
=
self
.
portal
.
portal_catalog
(
uid
=
instance
.
getUid
(),
select_dict
=
{
"indexation_timestamp"
:
None
}
)[
0
].
indexation_timestamp
self
.
assertEqual
(
new_indexation_timestamp
,
indexation_timestamp
)
self
.
assertEqual
(
True
,
instance
.
setErrorStatus
(
"TEST123 %s"
%
instance
.
getUid
(),
reindex
=
1
))
self
.
tic
()
new_indexation_timestamp
=
self
.
portal
.
portal_catalog
(
uid
=
instance
.
getUid
(),
select_dict
=
{
"indexation_timestamp"
:
None
}
)[
0
].
indexation_timestamp
self
.
assertNotEqual
(
new_indexation_timestamp
,
indexation_timestamp
)
def
test_setErrorStatus
(
self
):
since
=
rfc1123_date
(
DateTime
())
created_at
=
since
def
getExpectedCacheDict
(
doc
):
return
json
.
dumps
({
"user"
:
"ERP5TypeTestCase"
,
'created_at'
:
'%s'
%
created_at
,
'since'
:
'%s'
%
since
,
'state'
:
""
,
"text"
:
"#error TEST123 %s"
%
doc
.
getUid
()
})
def
getBaseExpectedDict
(
doc
):
return
{
"user"
:
"ERP5TypeTestCase"
,
'created_at'
:
'%s'
%
created_at
,
u'since'
:
u'%s'
%
since
,
u'state'
:
u""
,
u"text"
:
u"#error TEST123 %s"
%
doc
.
getUid
(),
'no_data_since_15_minutes'
:
0
,
'no_data_since_5_minutes'
:
0
}
# Check Compute Node
self
.
assertEqual
(
True
,
self
.
compute_node
.
setErrorStatus
(
"TEST123 %s"
%
self
.
compute_node
.
getUid
()))
self
.
assertEqual
(
self
.
compute_node
.
_getCachedAccessInfo
(),
getExpectedCacheDict
(
self
.
compute_node
))
self
.
assertEqual
(
self
.
compute_node
.
getAccessStatus
(),
getBaseExpectedDict
(
self
.
compute_node
))
self
.
assertEqual
(
False
,
self
.
compute_node
.
setErrorStatus
(
"TEST123 %s"
%
self
.
compute_node
.
getUid
()))
# Check Software Installation
installation
=
self
.
start_requested_software_installation
self
.
assertEqual
(
True
,
installation
.
setErrorStatus
(
"TEST123 %s"
%
installation
.
getUid
()))
self
.
assertEqual
(
installation
.
_getCachedAccessInfo
(),
getExpectedCacheDict
(
installation
))
self
.
assertEqual
(
installation
.
getAccessStatus
(),
getBaseExpectedDict
(
installation
))
self
.
assertEqual
(
False
,
installation
.
setErrorStatus
(
"TEST123 %s"
%
installation
.
getUid
()))
# Compute Partition
partition
=
self
.
compute_node
.
partition1
self
.
assertEqual
(
True
,
partition
.
setErrorStatus
(
"TEST123 %s"
%
partition
.
getUid
()))
self
.
assertEqual
(
partition
.
_getCachedAccessInfo
(),
getExpectedCacheDict
(
partition
))
self
.
assertEqual
(
partition
.
getAccessStatus
(),
getBaseExpectedDict
(
partition
))
self
.
assertEqual
(
False
,
partition
.
setErrorStatus
(
"TEST123 %s"
%
partition
.
getUid
()))
# Software Instance
instance
=
self
.
start_requested_software_instance
self
.
assertEqual
(
True
,
instance
.
setErrorStatus
(
"TEST123 %s"
%
instance
.
getUid
()))
self
.
assertEqual
(
instance
.
_getCachedAccessInfo
(),
getExpectedCacheDict
(
instance
))
self
.
assertEqual
(
instance
.
getAccessStatus
(),
getBaseExpectedDict
(
instance
))
self
.
assertEqual
(
False
,
instance
.
setErrorStatus
(
"TEST123 %s"
%
instance
.
getUid
()))
def
test_setBuildingStatus
(
self
):
since
=
rfc1123_date
(
DateTime
())
created_at
=
since
def
getExpectedCacheDict
(
doc
):
return
json
.
dumps
({
"user"
:
"ERP5TypeTestCase"
,
'created_at'
:
'%s'
%
created_at
,
'since'
:
'%s'
%
since
,
'state'
:
""
,
"text"
:
"#building TEST123 %s"
%
doc
.
getUid
()
})
def
getBaseExpectedDict
(
doc
):
return
{
"user"
:
"ERP5TypeTestCase"
,
'created_at'
:
'%s'
%
created_at
,
u'since'
:
u'%s'
%
since
,
u'state'
:
u""
,
u"text"
:
u"#building TEST123 %s"
%
doc
.
getUid
(),
'no_data_since_15_minutes'
:
0
,
'no_data_since_5_minutes'
:
0
}
# Check Software Installation
installation
=
self
.
start_requested_software_installation
self
.
assertEqual
(
True
,
installation
.
setBuildingStatus
(
"TEST123 %s"
%
installation
.
getUid
()))
self
.
assertEqual
(
installation
.
_getCachedAccessInfo
(),
getExpectedCacheDict
(
installation
))
self
.
assertEqual
(
installation
.
getAccessStatus
(),
getBaseExpectedDict
(
installation
))
self
.
assertEqual
(
False
,
installation
.
setBuildingStatus
(
"TEST123 %s"
%
installation
.
getUid
()))
class
TestSlapOSCloudSoftwareInstance
(
SlapOSTestCaseMixin
):
def
afterSetUp
(
self
):
SlapOSTestCaseMixin
.
afterSetUp
(
self
)
self
.
_makeTree
()
def
test_getXmlAsDict
(
self
):
simple_parameter_sample_xml
=
"""<?xml version='1.0' encoding='utf-8'?>
<instance>
<parameter id="p1é">v1é</parameter>
<parameter id="p2é">v2é</parameter>
</instance>
"""
self
.
assertEqual
(
self
.
software_instance
.
_getXmlAsDict
(
simple_parameter_sample_xml
),
{
'p1é'
:
'v1é'
,
'p2é'
:
'v2é'
})
def
test_getInstanceXmlAsDict
(
self
):
self
.
software_instance
.
setTextContent
(
"""<?xml version='1.0' encoding='utf-8'?>
<instance>
<parameter id="p1é">v1é</parameter>
<parameter id="p2é">v2é</parameter>
</instance>
"""
)
self
.
assertEqual
(
self
.
software_instance
.
getInstanceXmlAsDict
(),
{
'p1é'
:
'v1é'
,
'p2é'
:
'v2é'
})
def
test_getSlaXmlAsDict
(
self
):
self
.
software_instance
.
setSlaXml
(
"""<?xml version='1.0' encoding='utf-8'?>
<instance>
<parameter id="p1é">v1é</parameter>
<parameter id="p2é">v2é</parameter>
</instance>
"""
)
self
.
assertEqual
(
self
.
software_instance
.
getSlaXmlAsDict
(),
{
'p1é'
:
'v1é'
,
'p2é'
:
'v2é'
})
def
test_getConnectionXmlAsDict
(
self
):
self
.
software_instance
.
setConnectionXml
(
"""<?xml version='1.0' encoding='utf-8'?>
<instance>
<parameter id="p1é">v1é</parameter>
<parameter id="p2é">v2é</parameter>
</instance>
"""
)
self
.
assertEqual
(
self
.
software_instance
.
getConnectionXmlAsDict
(),
{
'p1é'
:
'v1é'
,
'p2é'
:
'v2é'
})
def
test_instanceXmlToDict
(
self
):
simple_parameter_sample_xml
=
"""<?xml version='1.0' encoding='utf-8'?>
<instance>
<parameter id="p1é">v1é</parameter>
<parameter id="p2é">v2é</parameter>
</instance>
"""
self
.
assertEqual
(
self
.
software_instance
.
_instanceXmlToDict
(
simple_parameter_sample_xml
),
# different from getXmlAsDict it don't encode things as utf-8
{
u'p1é'
:
u'v1é'
,
u'p2é'
:
u'v2é'
})
def
test_asParameterDict_not_allocated
(
self
):
self
.
assertRaises
(
ValueError
,
self
.
software_instance
.
_asParameterDict
)
def
test_asParameterDict
(
self
):
self
.
_makeComputeNode
()
self
.
_makeComplexComputeNode
(
with_slave
=
True
)
as_parameter_dict
=
self
.
start_requested_software_instance
.
_asParameterDict
()
self
.
assertSameSet
(
as_parameter_dict
.
keys
(),
[
'instance_guid'
,
'instance_title'
,
'root_instance_title'
,
'root_instance_short_title'
,
'xml'
,
'connection_xml'
,
'filter_xml'
,
'slap_computer_id'
,
'slap_computer_partition_id'
,
'slap_software_type'
,
'slap_software_release_url'
,
'slave_instance_list'
,
'ip_list'
,
'full_ip_list'
,
'timestamp'
])
self
.
assertEqual
(
as_parameter_dict
[
"instance_guid"
],
self
.
start_requested_software_instance
.
getReference
().
decode
(
"UTF-8"
)
)
self
.
assertEqual
(
as_parameter_dict
[
"instance_title"
],
self
.
start_requested_software_instance
.
getTitle
().
decode
(
"UTF-8"
)
)
self
.
assertEqual
(
as_parameter_dict
[
"xml"
],
self
.
start_requested_software_instance
.
getTextContent
()
)
self
.
assertEqual
(
as_parameter_dict
[
"connection_xml"
],
self
.
start_requested_software_instance
.
getConnectionXml
()
)
self
.
assertEqual
(
as_parameter_dict
[
"filter_xml"
],
self
.
start_requested_software_instance
.
getSlaXml
()
)
self
.
assertEqual
(
as_parameter_dict
[
"root_instance_title"
],
self
.
start_requested_software_instance
.
getSpecialiseTitle
().
decode
(
"UTF-8"
))
self
.
assertEqual
(
as_parameter_dict
[
"root_instance_short_title"
],
self
.
start_requested_software_instance
.
getSpecialiseShortTitle
().
decode
(
"UTF-8"
))
self
.
assertEqual
(
as_parameter_dict
[
"slap_computer_id"
],
self
.
compute_node
.
getReference
().
decode
(
"UTF-8"
))
self
.
assertEqual
(
as_parameter_dict
[
"slap_computer_partition_id"
],
"partition1"
)
self
.
assertEqual
(
len
(
as_parameter_dict
[
"slave_instance_list"
]),
1
)
self
.
assertSameSet
(
as_parameter_dict
[
"slave_instance_list"
][
0
].
keys
(),
[
'slave_title'
,
'slap_software_type'
,
'slave_reference'
,
'timestamp'
,
'xml'
,
'connection_xml'
])
self
.
assertEqual
(
self
.
start_requested_slave_instance
.
getTitle
().
decode
(
"UTF-8"
),
as_parameter_dict
[
"slave_instance_list"
][
0
][
"slave_title"
]
)
self
.
assertEqual
(
as_parameter_dict
[
"ip_list"
],
[(
u''
,
u'ip_address_1'
)])
# Since gateway isn't set both are the same.
self
.
assertEqual
(
as_parameter_dict
[
"full_ip_list"
],
[])
def
test_getInstanceTreeIpList
(
self
):
self
.
_makeComputeNode
()
self
.
_makeComplexComputeNode
(
with_slave
=
True
)
self
.
tic
()
self
.
assertEqual
([(
u''
,
u'ip_address_1'
)],
self
.
start_requested_software_instance
.
_getInstanceTreeIpList
())
class
TestSlapOSCloudSlapOSComputeNodeMixin_getCacheComputeNodeInformation
(
SlapOSTestCaseMixin
):
def
afterSetUp
(
self
):
SlapOSTestCaseMixin
.
afterSetUp
(
self
)
# Prepare compute_node
self
.
compute_node
=
self
.
portal
.
compute_node_module
.
template_compute_node
\
.
Base_createCloneDocument
(
batch_mode
=
1
)
self
.
compute_node
.
edit
(
title
=
"Compute Node %s"
%
self
.
new_id
,
reference
=
"TESTCOMP-%s"
%
self
.
new_id
)
if
getattr
(
self
,
"person"
,
None
)
is
not
None
:
self
.
compute_node
.
edit
(
source_administration_value
=
getattr
(
self
,
"person"
,
None
),
)
self
.
compute_node
.
validate
()
self
.
_addERP5Login
(
self
.
compute_node
)
self
.
tic
()
self
.
compute_node_id
=
self
.
compute_node
.
getReference
()
self
.
compute_node_user_id
=
self
.
compute_node
.
getUserId
()
self
.
pinDateTime
(
DateTime
())
def
beforeTearDown
(
self
):
self
.
unpinDateTime
()
self
.
_cleaupREQUEST
()
def
test_activate_getCacheComputeNodeInformation_first_access
(
self
):
#
# This is a port of
# TestSlapOSSlapToolgetFullComputerInformation.test_activate_getFullComputerInformation_first_access
#
self
.
_makeComplexComputeNode
(
with_slave
=
True
)
self
.
portal
.
REQUEST
[
'disable_isTestRun'
]
=
True
self
.
tic
()
self
.
login
(
self
.
compute_node_user_id
)
user
=
self
.
getPortalObject
().
portal_membership
.
getAuthenticatedMember
().
getUserName
()
self
.
compute_node
.
setAccessStatus
(
self
.
compute_node_id
)
refresh_etag
=
self
.
compute_node
.
_calculateRefreshEtag
()
body
,
etag
=
self
.
compute_node
.
_getComputeNodeInformation
(
user
,
refresh_etag
)
self
.
commit
()
first_etag
=
self
.
compute_node
.
_calculateRefreshEtag
()
first_body_fingerprint
=
hashData
(
self
.
compute_node
.
_getCacheComputeNodeInformation
(
self
.
compute_node_id
)
)
self
.
assertEqual
(
first_etag
,
etag
)
self
.
assertEqual
(
first_body_fingerprint
,
hashData
(
body
))
self
.
assertEqual
(
0
,
len
(
self
.
portal
.
portal_activities
.
getMessageList
()))
# Trigger the compute_node reindexation
# This should trigger a new etag, but the body should be the same
self
.
compute_node
.
reindexObject
()
self
.
commit
()
# Second access
# Check that the result is stable, as the indexation timestamp is not changed yet
current_activity_count
=
len
(
self
.
portal
.
portal_activities
.
getMessageList
())
self
.
compute_node
.
setAccessStatus
(
self
.
compute_node_id
)
refresh_etag
=
self
.
compute_node
.
_calculateRefreshEtag
()
body
,
etag
=
self
.
compute_node
.
_getComputeNodeInformation
(
user
,
refresh_etag
)
self
.
commit
()
self
.
assertEqual
(
first_etag
,
etag
)
self
.
assertEqual
(
first_body_fingerprint
,
hashData
(
body
))
self
.
assertEqual
(
current_activity_count
,
len
(
self
.
portal
.
portal_activities
.
getMessageList
()))
self
.
tic
()
# Third access, new calculation expected
# The retrieved informations comes from the cache
# But a new cache modification activity is triggered
self
.
compute_node
.
setAccessStatus
(
self
.
compute_node_id
)
refresh_etag
=
self
.
compute_node
.
_calculateRefreshEtag
()
body
,
etag
=
self
.
compute_node
.
_getComputeNodeInformation
(
user
,
refresh_etag
)
self
.
commit
()
second_etag
=
self
.
compute_node
.
_calculateRefreshEtag
()
second_body_fingerprint
=
hashData
(
self
.
compute_node
.
_getCacheComputeNodeInformation
(
self
.
compute_node_id
)
)
self
.
assertNotEqual
(
first_etag
,
second_etag
)
# The indexation timestamp does not impact the response body
self
.
assertEqual
(
first_body_fingerprint
,
second_body_fingerprint
)
self
.
assertEqual
(
first_etag
,
etag
)
self
.
assertEqual
(
first_body_fingerprint
,
hashData
(
body
))
self
.
assertEqual
(
1
,
len
(
self
.
portal
.
portal_activities
.
getMessageList
()))
# Execute the cache modification activity
self
.
tic
()
# 4th access
# The new etag value is now used
self
.
compute_node
.
setAccessStatus
(
self
.
compute_node_id
)
refresh_etag
=
self
.
compute_node
.
_calculateRefreshEtag
()
body
,
etag
=
self
.
compute_node
.
_getComputeNodeInformation
(
user
,
refresh_etag
)
self
.
commit
()
self
.
assertEqual
(
second_etag
,
etag
)
self
.
assertEqual
(
first_body_fingerprint
,
hashData
(
body
))
self
.
assertEqual
(
0
,
len
(
self
.
portal
.
portal_activities
.
getMessageList
()))
# Edit the instance
# This should trigger a new etag and a new body
self
.
stop_requested_software_instance
.
edit
(
text_content
=
self
.
generateSafeXml
())
self
.
commit
()
# 5th access
# Check that the result is stable, as the indexation timestamp is not changed yet
current_activity_count
=
len
(
self
.
portal
.
portal_activities
.
getMessageList
())
# Edition does not impact the etag
self
.
assertEqual
(
second_etag
,
self
.
compute_node
.
_calculateRefreshEtag
())
third_body_fingerprint
=
hashData
(
self
.
compute_node
.
_getCacheComputeNodeInformation
(
self
.
compute_node_id
)
)
# The edition impacts the response body
self
.
assertNotEqual
(
first_body_fingerprint
,
third_body_fingerprint
)
self
.
compute_node
.
setAccessStatus
(
self
.
compute_node_id
)
refresh_etag
=
self
.
compute_node
.
_calculateRefreshEtag
()
body
,
etag
=
self
.
compute_node
.
_getComputeNodeInformation
(
user
,
refresh_etag
)
self
.
commit
()
self
.
assertEqual
(
second_etag
,
etag
)
self
.
assertEqual
(
first_body_fingerprint
,
hashData
(
body
))
self
.
assertEqual
(
current_activity_count
,
len
(
self
.
portal
.
portal_activities
.
getMessageList
()))
self
.
tic
()
# 6th, the instance edition triggered an interaction workflow
# which updated the cache
self
.
compute_node
.
setAccessStatus
(
self
.
compute_node_id
)
refresh_etag
=
self
.
compute_node
.
_calculateRefreshEtag
()
body
,
etag
=
self
.
compute_node
.
_getComputeNodeInformation
(
user
,
refresh_etag
)
self
.
commit
()
third_etag
=
self
.
compute_node
.
_calculateRefreshEtag
()
self
.
assertNotEqual
(
second_etag
,
third_etag
)
self
.
assertEqual
(
third_etag
,
etag
)
self
.
assertEqual
(
third_body_fingerprint
,
hashData
(
body
))
self
.
assertEqual
(
0
,
len
(
self
.
portal
.
portal_activities
.
getMessageList
()))
# Remove the slave link to the partition
# Compute Node should loose permission to access the slave instance
self
.
start_requested_slave_instance
.
setAggregate
(
''
)
self
.
commit
()
# 7th access
# Check that the result is stable, as the indexation timestamp is not changed yet
current_activity_count
=
len
(
self
.
portal
.
portal_activities
.
getMessageList
())
# Edition does not impact the etag
self
.
assertEqual
(
third_etag
,
self
.
compute_node
.
_calculateRefreshEtag
())
# The edition does not impact the response body yet, as the aggregate relation
# is not yet unindex
self
.
assertEqual
(
third_body_fingerprint
,
hashData
(
self
.
compute_node
.
_getCacheComputeNodeInformation
(
self
.
compute_node_id
)
))
self
.
compute_node
.
setAccessStatus
(
self
.
compute_node_id
)
refresh_etag
=
self
.
compute_node
.
_calculateRefreshEtag
()
body
,
etag
=
self
.
compute_node
.
_getComputeNodeInformation
(
user
,
refresh_etag
)
self
.
commit
()
self
.
assertEqual
(
third_etag
,
etag
)
self
.
assertEqual
(
third_body_fingerprint
,
hashData
(
body
))
self
.
assertEqual
(
current_activity_count
,
len
(
self
.
portal
.
portal_activities
.
getMessageList
()))
self
.
tic
()
# 8th access
# changing the aggregate relation trigger the partition reindexation
# which trigger cache modification activity
# So, we should get the correct cached value
self
.
compute_node
.
setAccessStatus
(
self
.
compute_node_id
)
refresh_etag
=
self
.
compute_node
.
_calculateRefreshEtag
()
body
,
etag
=
self
.
compute_node
.
_getComputeNodeInformation
(
user
,
refresh_etag
)
self
.
commit
()
fourth_etag
=
self
.
compute_node
.
_calculateRefreshEtag
()
fourth_body_fingerprint
=
hashData
(
self
.
compute_node
.
_getCacheComputeNodeInformation
(
self
.
compute_node_id
)
)
self
.
assertNotEqual
(
third_etag
,
fourth_etag
)
# The indexation timestamp does not impact the response body
self
.
assertNotEqual
(
third_body_fingerprint
,
fourth_body_fingerprint
)
self
.
assertEqual
(
fourth_etag
,
etag
)
self
.
assertEqual
(
fourth_body_fingerprint
,
hashData
(
body
))
self
.
assertEqual
(
0
,
len
(
self
.
portal
.
portal_activities
.
getMessageList
()))
master/bt5/slapos_cloud/TestTemplateItem/portal_components/test.erp5.testSlapOSCloud.xml
0 → 100644
View file @
88bdb2d7
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"Test Component"
module=
"erp5.portal_type"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_recorded_property_dict
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAI=
</string>
</persistent>
</value>
</item>
<item>
<key>
<string>
default_reference
</string>
</key>
<value>
<string>
testSlapOSCloud
</string>
</value>
</item>
<item>
<key>
<string>
default_source_reference
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
test.erp5.testSlapOSCloud
</string>
</value>
</item>
<item>
<key>
<string>
portal_type
</string>
</key>
<value>
<string>
Test Component
</string>
</value>
</item>
<item>
<key>
<string>
sid
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
text_content_error_message
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
text_content_warning_message
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
version
</string>
</key>
<value>
<string>
erp5
</string>
</value>
</item>
<item>
<key>
<string>
workflow_history
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAM=
</string>
</persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"2"
aka=
"AAAAAAAAAAI="
>
<pickle>
<global
name=
"PersistentMapping"
module=
"Persistence.mapping"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
data
</string>
</key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"3"
aka=
"AAAAAAAAAAM="
>
<pickle>
<global
name=
"PersistentMapping"
module=
"Persistence.mapping"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
data
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
component_validation_workflow
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAQ=
</string>
</persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"4"
aka=
"AAAAAAAAAAQ="
>
<pickle>
<global
name=
"WorkflowHistoryList"
module=
"Products.ERP5Type.Workflow"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_log
</string>
</key>
<value>
<list>
<dictionary>
<item>
<key>
<string>
action
</string>
</key>
<value>
<string>
validate
</string>
</value>
</item>
<item>
<key>
<string>
validation_state
</string>
</key>
<value>
<string>
validated
</string>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/compute_node_slap_interface_workflow/script_ComputeNode_reportBang.py
View file @
88bdb2d7
...
...
@@ -11,3 +11,5 @@ for compute_partition in [x for x in compute_node.contentValues(portal_type='Com
relative_url
=
instance
.
getRelativeUrl
(),
reference
=
instance
.
getReference
(),
comment
=
state_change
.
kwargs
.
get
(
'comment'
,
''
))
compute_node
.
setErrorStatus
(
'bang'
)
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/compute_node_slap_interface_workflow/script_ComputeNode_reportBang.xml
View file @
88bdb2d7
...
...
@@ -52,6 +52,12 @@
<key>
<string>
_params
</string>
</key>
<value>
<string>
state_change
</string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
script_ComputeNode_reportBang
</string>
</value>
...
...
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_bangInstanceTree.py
View file @
88bdb2d7
...
...
@@ -3,6 +3,9 @@ instance = state_change['object']
assert
instance
.
getPortalType
()
in
[
"Slave Instance"
,
"Software Instance"
]
instance
.
edit
(
bang_timestamp
=
int
(
DateTime
()))
key
=
"%s_bangstamp"
%
instance
.
getReference
()
instance
.
setLastData
(
key
,
str
(
int
(
instance
.
getModificationDate
())))
comment
=
state_change
.
kwargs
[
'comment'
]
# comment is required to pass the transition
if
state_change
.
kwargs
[
'bang_tree'
]:
from
Products.ZSQLCatalog.SQLCatalog
import
Query
,
NegatedQuery
...
...
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_bangInstanceTree.xml
View file @
88bdb2d7
...
...
@@ -60,6 +60,12 @@
</tuple>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
script_RequestedInstance_bangInstanceTree
</string>
</value>
...
...
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_generateCertificate.py
0 → 100644
View file @
88bdb2d7
instance
=
state_change
[
'object'
]
if
instance
.
getDestinationReference
()
is
not
None
:
raise
ValueError
(
"Certificate still active."
)
if
instance
.
getPortalType
()
!=
"Software Instance"
:
# Skip if the instance isn't a Software Instance,
# since Shared Instances cannot find the object.
return
ca
=
context
.
getPortalObject
().
portal_certificate_authority
certificate_dict
=
ca
.
getNewCertificate
(
instance
.
getReference
())
edit_kw
=
{
'destination_reference'
:
certificate_dict
[
'id'
],
'ssl_key'
:
certificate_dict
[
'key'
],
'ssl_certificate'
:
certificate_dict
[
'certificate'
]
}
instance
.
edit
(
**
edit_kw
)
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_generateCertificate.xml
0 → 100644
View file @
88bdb2d7
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"Workflow Script"
module=
"erp5.portal_type"
/>
</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>
_params
</string>
</key>
<value>
<string>
state_change
</string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
script_RequestedInstance_generateCertificate
</string>
</value>
</item>
<item>
<key>
<string>
portal_type
</string>
</key>
<value>
<string>
Workflow Script
</string>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_rename.py
View file @
88bdb2d7
...
...
@@ -29,4 +29,12 @@ if len(request_software_instance_list) == 1:
raise
ValueError
,
"Too many instances '%s' found: %s"
%
(
software_title
,
[
x
.
path
for
x
in
request_software_instance_list
])
# Change the title
previous_title
=
instance
.
getTitle
()
instance
.
edit
(
title
=
software_title
,
activate_kw
=
{
'tag'
:
tag
})
# Ensure that the latest date is reset for both new and old instance
hosting
=
instance
.
getSpecialise
()
for
name
in
[
previous_title
,
software_title
]:
# reset request cache
key
=
'_'
.
join
([
hosting
,
name
])
instance
.
setLastData
({},
key
=
key
)
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_rename.xml
View file @
88bdb2d7
...
...
@@ -52,6 +52,12 @@
<key>
<string>
_params
</string>
</key>
<value>
<string>
state_change
</string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
script_RequestedInstance_rename
</string>
</value>
...
...
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_revokeCertificate.py
0 → 100644
View file @
88bdb2d7
instance
=
state_change
[
'object'
]
portal
=
instance
.
getPortalObject
()
if
instance
.
getSslKey
()
is
not
None
or
instance
.
getSslCertificate
()
is
not
None
:
instance
.
edit
(
ssl_key
=
None
,
ssl_certificate
=
None
)
destination_reference
=
instance
.
getDestinationReference
()
if
destination_reference
is
None
:
raise
ValueError
(
'No certificate'
)
try
:
portal
.
portal_certificate_authority
\
.
revokeCertificate
(
instance
.
getDestinationReference
())
except
ValueError
:
# Ignore already revoked certificates, as OpenSSL backend is
# non transactional, so it is ok to allow multiple tries to destruction
# even if certificate was already revoked
pass
instance
.
setDestinationReference
(
None
)
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_revokeCertificate.xml
0 → 100644
View file @
88bdb2d7
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"Workflow Script"
module=
"erp5.portal_type"
/>
</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>
_params
</string>
</key>
<value>
<string>
state_change
</string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
script_RequestedInstance_revokeCertificate
</string>
</value>
</item>
<item>
<key>
<string>
portal_type
</string>
</key>
<value>
<string>
Workflow Script
</string>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_updateConnectionInformation.py
View file @
88bdb2d7
...
...
@@ -13,3 +13,5 @@ edit_kw = {
instance
.
edit
(
**
edit_kw
)
# Prevent storing broken XML in text content (which prevent to update parameters after)
context
.
Instance_checkConsistency
(
state_change
)
instance
.
setLastData
(
connection_xml
)
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_updateConnectionInformation.xml
View file @
88bdb2d7
...
...
@@ -52,6 +52,12 @@
<key>
<string>
_params
</string>
</key>
<value>
<string>
state_change
</string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
script_RequestedInstance_updateConnectionInformation
</string>
</value>
...
...
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequesterInstance_request.py
View file @
88bdb2d7
...
...
@@ -79,15 +79,10 @@ if (request_software_instance is None):
id_group
=
'slap_software_instance_reference'
,
id_generator
=
'uid'
)
new_content_kw
=
{}
if
is_slave
==
True
:
software_instance_portal_type
=
"Slave Instance"
else
:
software_instance_portal_type
=
"Software Instance"
certificate_dict
=
portal
.
portal_certificate_authority
.
getNewCertificate
(
reference
)
new_content_kw
[
'destination_reference'
]
=
certificate_dict
[
'id'
]
new_content_kw
[
'ssl_key'
]
=
certificate_dict
[
'key'
]
new_content_kw
[
'ssl_certificate'
]
=
certificate_dict
[
'certificate'
]
module
=
portal
.
getDefaultModule
(
portal_type
=
"Software Instance"
)
request_software_instance
=
module
.
newContent
(
...
...
@@ -95,9 +90,9 @@ if (request_software_instance is None):
title
=
software_title
,
specialise_value
=
instance_tree
,
reference
=
reference
,
activate_kw
=
{
'tag'
:
tag
},
**
new_content_kw
activate_kw
=
{
'tag'
:
tag
}
)
request_software_instance
.
generateCertificate
()
request_software_instance
.
validate
()
if
software_instance_portal_type
==
"Software Instance"
:
# Include Certificate Login so Instance become a User
...
...
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/script_RequesterInstance_request.xml
View file @
88bdb2d7
...
...
@@ -52,6 +52,12 @@
<key>
<string>
_params
</string>
</key>
<value>
<string>
state_change
</string>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
script_RequesterInstance_request
</string>
</value>
...
...
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/state_destroy_requested.xml
View file @
88bdb2d7
...
...
@@ -17,9 +17,11 @@
<value>
<tuple>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_bang
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_generate_certificate
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_report_compute_partition_error
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_request_instance
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_request_transfer
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_revoke_certificate
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_unallocate_partition
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_update_connection
</string>
</tuple>
...
...
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/state_draft.xml
View file @
88bdb2d7
...
...
@@ -17,9 +17,11 @@
<value>
<tuple>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_bang
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_generate_certificate
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_request_start
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_request_stop
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_request_transfer
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_revoke_certificate
</string>
</tuple>
</value>
</item>
...
...
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/state_start_requested.xml
View file @
88bdb2d7
...
...
@@ -18,6 +18,7 @@
<tuple>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_allocate_partition
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_bang
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_generate_certificate
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_rename
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_report_compute_partition_error
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_request_destroy
</string>
...
...
@@ -25,6 +26,7 @@
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_request_start
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_request_stop
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_request_transfer
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_revoke_certificate
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_update_connection
</string>
</tuple>
</value>
...
...
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/state_stop_requested.xml
View file @
88bdb2d7
...
...
@@ -18,6 +18,7 @@
<tuple>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_allocate_partition
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_bang
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_generate_certificate
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_rename
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_report_compute_partition_error
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_request_destroy
</string>
...
...
@@ -25,6 +26,7 @@
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_request_start
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_request_stop
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_request_transfer
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_revoke_certificate
</string>
<string>
destination/portal_workflow/instance_slap_interface_workflow/transition_update_connection
</string>
</tuple>
</value>
...
...
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/transition_generate_certificate.xml
0 → 100644
View file @
88bdb2d7
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"Workflow Transition"
module=
"erp5.portal_type"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
action
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
action_name
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
categories
</string>
</key>
<value>
<tuple>
<string>
action_type/workflow
</string>
<string>
after_script/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_generateCertificate
</string>
</tuple>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
guard_permission
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
icon
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
transition_generate_certificate
</string>
</value>
</item>
<item>
<key>
<string>
portal_type
</string>
</key>
<value>
<string>
Workflow Transition
</string>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<string>
Generate Certificate
</string>
</value>
</item>
<item>
<key>
<string>
trigger_type
</string>
</key>
<value>
<int>
2
</int>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
master/bt5/slapos_cloud/WorkflowTemplateItem/portal_workflow/instance_slap_interface_workflow/transition_revoke_certificate.xml
0 → 100644
View file @
88bdb2d7
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"Workflow Transition"
module=
"erp5.portal_type"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
action
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
action_name
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
categories
</string>
</key>
<value>
<tuple>
<string>
action_type/workflow
</string>
<string>
after_script/portal_workflow/instance_slap_interface_workflow/script_RequestedInstance_revokeCertificate
</string>
</tuple>
</value>
</item>
<item>
<key>
<string>
description
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
guard_permission
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
icon
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
transition_revoke_certificate
</string>
</value>
</item>
<item>
<key>
<string>
portal_type
</string>
</key>
<value>
<string>
Workflow Transition
</string>
</value>
</item>
<item>
<key>
<string>
title
</string>
</key>
<value>
<string>
Revoke Certificate
</string>
</value>
</item>
<item>
<key>
<string>
trigger_type
</string>
</key>
<value>
<int>
2
</int>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
master/bt5/slapos_cloud/bt/template_action_path_list
View file @
88bdb2d7
Computer Model | view_capacity
Computer Network | view_compute_node_list
Computer Network | view_software_release
Compute Partition | unfiltered_tracking_list
Compute Node | compute_node_usage
Compute Node | tracking
Compute Node | view_capacity
Compute Partition | unfiltered_tracking_list
Computer Model | view_capacity
Computer Network | view_compute_node_list
Computer Network | view_software_release
Hosting Subscription Module | view
Hosting Subscription | view
Instance Tree Module | view
...
...
@@ -34,4 +34,4 @@ Software Instance | view_rename_and_request_stop
Software Release | usable_compute_node
Software Release | usable_network
Software Release | view_capacity
System Preference | slapos_system_preference
System Preference | slapos_system_preference
\ No newline at end of file
master/bt5/slapos_cloud/bt/template_mixin_id_list
View file @
88bdb2d7
mixin.erp5.SlapOSCacheMixin
\ No newline at end of file
mixin.erp5.SlapOSCacheMixin
mixin.erp5.SlapOSComputeNodeMixin
mixin.erp5.SlapOSComputePartitionMixin
\ No newline at end of file
master/bt5/slapos_cloud/bt/template_path_list
View file @
88bdb2d7
...
...
@@ -19,6 +19,8 @@ portal_alarms/slapos_stop_collect_instance
portal_alarms/slapos_update_compute_node_capacity_scope
portal_caches/access_status_data_cache_factory
portal_caches/access_status_data_cache_factory/volatile_cache_plugin
portal_caches/compute_node_information_cache_factory
portal_caches/compute_node_information_cache_factory/persistent_cache_plugin
portal_caches/last_stored_data_cache_factory
portal_caches/last_stored_data_cache_factory/volatile_cache_plugin
product_module/compute_node
...
...
master/bt5/slapos_cloud/bt/template_portal_type_base_category_list
View file @
88bdb2d7
Computer Model | source_administration
Computer Network | source_administration
Compute Node | destination_section
Compute Node | source_administration
Computer Model | source_administration
Computer Network | source_administration
Instance Tree Module | business_application
Instance Tree | destination_section
Slave Instance | aggregate
...
...
master/bt5/slapos_cloud/bt/template_portal_type_type_mixin_list
View file @
88bdb2d7
Compute Node | SlapOSCacheMixin
Compute Node | SlapOSComputeNodeMixin
Compute Partition | SlapOSCacheMixin
Compute Partition | SlapOSComputePartitionMixin
Person | SlapOSCacheMixin
\ No newline at end of file
master/bt5/slapos_cloud/bt/template_test_id_list
View file @
88bdb2d7
...
...
@@ -13,4 +13,5 @@ test.erp5.testSlapOSCloudConstraint
test.erp5.testSlapOSCloudUpgrader
test.erp5.testSlapOSCloudShadow
test.erp5.SlapOSTestCaseMixin
test.erp5.SlapOSTestCaseDefaultScenarioMixin
\ No newline at end of file
test.erp5.SlapOSTestCaseDefaultScenarioMixin
test.erp5.testSlapOSCloud
\ No newline at end of file
master/bt5/slapos_crm/TestTemplateItem/portal_components/test.erp5.testSlapOSCRMSkins.py
View file @
88bdb2d7
...
...
@@ -814,7 +814,7 @@ class TestComputeNode_hasContactedRecently(SlapOSTestCaseMixinWithAbort):
@
simulate
(
'ComputeNode_getCreationDate'
,
'*args, **kwargs'
,
'return DateTime() - 32'
)
def
test_ComputeNode_hasContactedRecently_memcached
(
self
):
compute_node
=
self
.
_makeComputeNode
()[
0
]
compute_node
.
setAccessStatus
(
"
#access
"
)
compute_node
.
setAccessStatus
(
""
)
self
.
tic
()
compute_node
.
getCreationDate
=
self
.
portal
.
ComputeNode_getCreationDate
...
...
@@ -827,7 +827,7 @@ class TestComputeNode_hasContactedRecently(SlapOSTestCaseMixinWithAbort):
compute_node
=
self
.
_makeComputeNode
()[
0
]
try
:
self
.
pinDateTime
(
DateTime
()
-
32
)
compute_node
.
setAccessStatus
(
"
#access
"
)
compute_node
.
setAccessStatus
(
""
)
finally
:
self
.
unpinDateTime
()
...
...
@@ -843,7 +843,7 @@ class TestComputeNode_hasContactedRecently(SlapOSTestCaseMixinWithAbort):
compute_node
=
self
.
_makeComputeNode
()[
0
]
try
:
self
.
pinDateTime
(
DateTime
()
-
32
)
compute_node
.
setAccessStatus
(
"
#access
"
)
compute_node
.
setAccessStatus
(
""
)
finally
:
self
.
unpinDateTime
()
...
...
@@ -1008,7 +1008,7 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
try
:
d
=
DateTime
()
-
1.1
self
.
pinDateTime
(
d
)
compute_node
.
setAccessStatus
(
"
#access
"
)
compute_node
.
setAccessStatus
(
""
)
finally
:
self
.
unpinDateTime
()
...
...
@@ -1045,7 +1045,7 @@ class TestSlapOSComputeNode_CheckState(TestCRMSkinsMixin):
try
:
self
.
pinDateTime
(
DateTime
()
-
1.1
)
compute_node
.
setAccessStatus
(
"
#access
"
)
compute_node
.
setAccessStatus
(
""
)
finally
:
self
.
unpinDateTime
()
...
...
@@ -1275,7 +1275,7 @@ class TestSlapOSHasError(SlapOSTestCaseMixin):
self
.
_makeComputeNode
()
self
.
_makeComputePartitionList
()
instance
.
set
AccessStatus
(
"#error
"
)
instance
.
set
ErrorStatus
(
"
"
)
self
.
assertEqual
(
instance
.
SoftwareInstance_hasReportedError
(),
None
)
...
...
@@ -1283,7 +1283,7 @@ class TestSlapOSHasError(SlapOSTestCaseMixin):
self
.
assertEqual
(
str
(
instance
.
SoftwareInstance_hasReportedError
()),
'#error '
)
instance
.
setAccessStatus
(
"
#access
"
)
instance
.
setAccessStatus
(
""
)
self
.
assertEqual
(
instance
.
SoftwareInstance_hasReportedError
(),
None
)
def
test_SoftwareInstallation_hasReportedError
(
self
):
...
...
@@ -1298,14 +1298,14 @@ class TestSlapOSHasError(SlapOSTestCaseMixin):
error_date
=
DateTime
()
try
:
self
.
pinDateTime
(
error_date
)
installation
.
set
AccessStatus
(
"#error
"
)
installation
.
set
ErrorStatus
(
"
"
)
finally
:
self
.
unpinDateTime
()
self
.
assertEqual
(
rfc1123_date
(
installation
.
SoftwareInstallation_hasReportedError
()),
rfc1123_date
(
error_date
))
installation
.
set
AccessStatus
(
"#building
"
)
installation
.
set
BuildingStatus
(
"
"
)
self
.
assertEqual
(
installation
.
SoftwareInstallation_hasReportedError
(),
None
)
...
...
@@ -1352,7 +1352,7 @@ class TestSlapOSHasError(SlapOSTestCaseMixin):
"slapos-crm-instance-tree-instance-state.notification"
),
instance_tree
.
InstanceTree_checkSoftwareInstanceState
())
instance
.
setAccessStatus
(
"
#access
"
)
instance
.
setAccessStatus
(
""
)
self
.
assertEqual
(
None
,
instance_tree
.
InstanceTree_checkSoftwareInstanceState
())
...
...
@@ -1455,7 +1455,7 @@ class TestSlapOSHasError(SlapOSTestCaseMixin):
instance
.
requestInstance
(
**
kw
)
self
.
tic
()
instance
.
setAccessStatus
(
"
#access
"
)
instance
.
setAccessStatus
(
""
)
self
.
assertEqual
(
'Visited by InstanceTree_createSupportRequestEvent %s %s'
%
\
...
...
@@ -1490,7 +1490,7 @@ class TestSlapOSHasError(SlapOSTestCaseMixin):
self
.
_makeComputePartitionList
()
instance
.
setAggregateValue
(
self
.
compute_node
.
partition1
)
instance
.
set
AccessStatus
(
"#error
"
)
instance
.
set
ErrorStatus
(
"
"
)
self
.
assertEqual
(
None
,
instance_tree
.
InstanceTree_checkSoftwareInstanceState
())
...
...
master/bt5/slapos_slap_tool/ExtensionTemplateItem/portal_components/extension.erp5.SlapOSSlapTool.py
View file @
88bdb2d7
...
...
@@ -17,30 +17,29 @@ def getComputeNodeReferenceAndUserId(item):
compute_node
=
partition
.
getParentValue
()
if
compute_node
is
not
None
and
compute_node
.
getValidationState
()
==
'validated'
:
return
compute_node
.
getReference
(),
compute_node
.
getUserId
()
return
None
,
None
return
compute_node
,
compute_node
.
getReference
(),
compute_node
.
getUserId
()
return
None
,
None
,
None
def
Item_activateFillComputeNodeInformationCache
(
state_change
):
item
=
state_change
[
'object'
]
portal
=
item
.
getPortalObject
()
compute_node_reference
,
user_id
=
getComputeNodeReferenceAndUserId
(
item
)
if
compute_node
_reference
is
None
:
compute_node
,
compute_node
_reference
,
user_id
=
getComputeNodeReferenceAndUserId
(
item
)
if
compute_node
is
None
:
return
None
if
user_id
is
None
:
return
None
user
=
portal
.
acl_users
.
getUserById
(
user_id
)
if
user
is
None
:
raise
ValueError
(
"User %s not found"
%
user_id
)
sm
=
getSecurityManager
()
try
:
newSecurityManager
(
None
,
user
)
portal
.
portal_slap
.
_activateFillComputeNodeInformationCache
(
compute_node_reference
,
compute_node_reference
)
compute_node
.
_activateFillComputeNodeInformationCache
(
compute_node_reference
)
finally
:
setSecurityManager
(
sm
)
...
...
master/bt5/slapos_slap_tool/TestTemplateItem/portal_components/test.erp5.testSlapOSSlapTool.py
View file @
88bdb2d7
...
...
@@ -78,16 +78,16 @@ class TestSlapOSSlapToolgetFullComputerInformation(TestSlapOSSlapToolMixin):
self
.
tic
()
self
.
login
(
self
.
compute_node_user_id
)
self
.
portal_slap
.
getFullComputerInformation
(
self
.
compute_node_id
)
# First access.
# Cache has been filled by interaction workflow
# (luckily, it seems the cache is filled after everything is indexed)
response
=
self
.
portal_slap
.
getFullComputerInformation
(
self
.
compute_node_id
)
self
.
commit
()
first_etag
=
self
.
portal_slap
.
_calculateRefreshEtag
()
first_etag
=
self
.
compute_node
.
_calculateRefreshEtag
()
first_body_fingerprint
=
hashData
(
self
.
portal_slap
.
_getCacheComputeNodeInformation
(
self
.
compute_node_id
,
self
.
compute_node_id
)
self
.
compute_node
.
_getCacheComputeNodeInformation
(
self
.
compute_node_id
)
)
self
.
assertEqual
(
200
,
response
.
status
)
self
.
assertTrue
(
'last-modified'
not
in
response
.
headers
)
...
...
@@ -120,10 +120,9 @@ class TestSlapOSSlapToolgetFullComputerInformation(TestSlapOSSlapToolMixin):
self
.
commit
()
self
.
assertEqual
(
200
,
response
.
status
)
self
.
assertTrue
(
'last-modified'
not
in
response
.
headers
)
second_etag
=
self
.
portal_slap
.
_calculateRefreshEtag
()
second_etag
=
self
.
compute_node
.
_calculateRefreshEtag
()
second_body_fingerprint
=
hashData
(
self
.
portal_slap
.
_getCacheComputeNodeInformation
(
self
.
compute_node_id
,
self
.
compute_node_id
)
self
.
compute_node
.
_getCacheComputeNodeInformation
(
self
.
compute_node_id
)
)
self
.
assertNotEqual
(
first_etag
,
second_etag
)
# The indexation timestamp does not impact the response body
...
...
@@ -154,10 +153,9 @@ class TestSlapOSSlapToolgetFullComputerInformation(TestSlapOSSlapToolMixin):
# Check that the result is stable, as the indexation timestamp is not changed yet
current_activity_count
=
len
(
self
.
portal
.
portal_activities
.
getMessageList
())
# Edition does not impact the etag
self
.
assertEqual
(
second_etag
,
self
.
portal_slap
.
_calculateRefreshEtag
())
self
.
assertEqual
(
second_etag
,
self
.
compute_node
.
_calculateRefreshEtag
())
third_body_fingerprint
=
hashData
(
self
.
portal_slap
.
_getCacheComputeNodeInformation
(
self
.
compute_node_id
,
self
.
compute_node_id
)
self
.
compute_node
.
_getCacheComputeNodeInformation
(
self
.
compute_node_id
)
)
# The edition impacts the response body
self
.
assertNotEqual
(
first_body_fingerprint
,
third_body_fingerprint
)
...
...
@@ -177,7 +175,7 @@ class TestSlapOSSlapToolgetFullComputerInformation(TestSlapOSSlapToolMixin):
self
.
commit
()
self
.
assertEqual
(
200
,
response
.
status
)
self
.
assertTrue
(
'last-modified'
not
in
response
.
headers
)
third_etag
=
self
.
portal_slap
.
_calculateRefreshEtag
()
third_etag
=
self
.
compute_node
.
_calculateRefreshEtag
()
self
.
assertNotEqual
(
second_etag
,
third_etag
)
self
.
assertEqual
(
third_etag
,
response
.
headers
.
get
(
'etag'
))
self
.
assertEqual
(
third_body_fingerprint
,
hashData
(
response
.
body
))
...
...
@@ -192,12 +190,11 @@ class TestSlapOSSlapToolgetFullComputerInformation(TestSlapOSSlapToolMixin):
# Check that the result is stable, as the indexation timestamp is not changed yet
current_activity_count
=
len
(
self
.
portal
.
portal_activities
.
getMessageList
())
# Edition does not impact the etag
self
.
assertEqual
(
third_etag
,
self
.
portal_slap
.
_calculateRefreshEtag
())
self
.
assertEqual
(
third_etag
,
self
.
compute_node
.
_calculateRefreshEtag
())
# The edition does not impact the response body yet, as the aggregate relation
# is not yet unindex
self
.
assertEqual
(
third_body_fingerprint
,
hashData
(
self
.
portal_slap
.
_getCacheComputeNodeInformation
(
self
.
compute_node_id
,
self
.
compute_node_id
)
self
.
compute_node
.
_getCacheComputeNodeInformation
(
self
.
compute_node_id
)
))
response
=
self
.
portal_slap
.
getFullComputerInformation
(
self
.
compute_node_id
)
self
.
commit
()
...
...
@@ -217,10 +214,9 @@ class TestSlapOSSlapToolgetFullComputerInformation(TestSlapOSSlapToolMixin):
self
.
commit
()
self
.
assertEqual
(
200
,
response
.
status
)
self
.
assertTrue
(
'last-modified'
not
in
response
.
headers
)
fourth_etag
=
self
.
portal_slap
.
_calculateRefreshEtag
()
fourth_etag
=
self
.
compute_node
.
_calculateRefreshEtag
()
fourth_body_fingerprint
=
hashData
(
self
.
portal_slap
.
_getCacheComputeNodeInformation
(
self
.
compute_node_id
,
self
.
compute_node_id
)
self
.
compute_node
.
_getCacheComputeNodeInformation
(
self
.
compute_node_id
)
)
self
.
assertNotEqual
(
third_etag
,
fourth_etag
)
# The indexation timestamp does not impact the response body
...
...
@@ -733,43 +729,9 @@ class TestSlapOSSlapToolComputeNodeAccess(TestSlapOSSlapToolMixin):
response
=
self
.
portal_slap
.
computerBang
(
self
.
compute_node_id
,
error_log
)
self
.
assertEqual
(
'None'
,
response
)
created_at
=
rfc1123_date
(
DateTime
())
since
=
created_at
response
=
self
.
portal_slap
.
getComputerStatus
(
self
.
compute_node_id
)
# check returned XML
xml_fp
=
StringIO
.
StringIO
()
xml
.
dom
.
ext
.
PrettyPrint
(
xml
.
dom
.
ext
.
reader
.
Sax
.
FromXml
(
response
.
body
),
stream
=
xml_fp
)
xml_fp
.
seek
(
0
)
got_xml
=
xml_fp
.
read
()
expected_xml
=
"""
\
<?xml version='1.0' encoding='UTF-8'?>
<marshal>
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data_since_15_minutes</string>
<int>0</int>
<string>no_data_since_5_minutes</string>
<int>0</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
<string/>
<string>text</string>
<string>#error bang</string>
<string>user</string>
<string>%(compute_node_id)s</string>
</dictionary>
</marshal>
"""
%
dict
(
created_at
=
created_at
,
since
=
since
,
compute_node_id
=
self
.
compute_node_id
,
)
self
.
assertEqual
(
expected_xml
,
got_xml
,
'
\
n
'
.
join
([
q
for
q
in
difflib
.
unified_diff
(
expected_xml
.
split
(
'
\
n
'
),
got_xml
.
split
(
'
\
n
'
))]))
# We do not assert getComputerStatus on this test, since
# the change of the timestamp is part of reportComputeNodeBang
self
.
assertComputeNodeBangSimulator
((),
{
'comment'
:
error_log
})
finally
:
if
os
.
path
.
exists
(
self
.
compute_node_bang_simulator
):
...
...
@@ -2635,43 +2597,9 @@ class TestSlapOSSlapToolPersonAccess(TestSlapOSSlapToolMixin):
response
=
self
.
portal_slap
.
computerBang
(
self
.
compute_node_id
,
error_log
)
self
.
assertEqual
(
'None'
,
response
)
created_at
=
rfc1123_date
(
DateTime
())
since
=
created_at
response
=
self
.
portal_slap
.
getComputerStatus
(
self
.
compute_node_id
)
# check returned XML
xml_fp
=
StringIO
.
StringIO
()
xml
.
dom
.
ext
.
PrettyPrint
(
xml
.
dom
.
ext
.
reader
.
Sax
.
FromXml
(
response
.
body
),
stream
=
xml_fp
)
xml_fp
.
seek
(
0
)
got_xml
=
xml_fp
.
read
()
expected_xml
=
"""
\
<?xml version='1.0' encoding='UTF-8'?>
<marshal>
<dictionary id='i2'>
<string>created_at</string>
<string>%(created_at)s</string>
<string>no_data_since_15_minutes</string>
<int>0</int>
<string>no_data_since_5_minutes</string>
<int>0</int>
<string>since</string>
<string>%(since)s</string>
<string>state</string>
<string/>
<string>text</string>
<string>#error bang</string>
<string>user</string>
<string>%(person_reference)s</string>
</dictionary>
</marshal>
"""
%
dict
(
created_at
=
created_at
,
since
=
since
,
person_reference
=
self
.
person_reference
,
)
self
.
assertEqual
(
expected_xml
,
got_xml
,
'
\
n
'
.
join
([
q
for
q
in
difflib
.
unified_diff
(
expected_xml
.
split
(
'
\
n
'
),
got_xml
.
split
(
'
\
n
'
))]))
# We do not assert getComputerStatus on this test, since
# the change of the timestamp is part of reportComputeNodeBang
self
.
assertComputeNodeBangSimulator
((),
{
'comment'
:
error_log
})
finally
:
if
os
.
path
.
exists
(
self
.
compute_node_bang_simulator
):
...
...
master/bt5/slapos_slap_tool/ToolComponentTemplateItem/portal_components/tool.erp5.SlapTool.py
View file @
88bdb2d7
...
...
@@ -38,37 +38,20 @@ from Products.DCWorkflow.DCWorkflow import ValidationFailed
from
Products.ERP5Type.Globals
import
InitializeClass
from
Products.ERP5Type.Tool.BaseTool
import
BaseTool
from
Products.ERP5Type
import
Permissions
from
Products.ERP5Type.Cache
import
DEFAULT_CACHE_SCOPE
from
Products.ERP5Type.Cache
import
CachingMethod
from
lxml
import
etree
import
time
from
Products.ERP5Type.tests.utils
import
DummyMailHostMixin
try
:
from
slapos.slap.slap
import
(
Computer
as
ComputeNode
,
ComputerPartition
as
SlapComputePartition
,
SoftwareInstance
,
SoftwareRelease
)
from
slapos.util
import
dict2xml
,
xml2dict
,
calculate_dict_hash
,
loads
,
dumps
Computer
as
ComputeNode
)
from
slapos.util
import
dict2xml
,
calculate_dict_hash
,
loads
,
dumps
except
ImportError
:
# Do no prevent instance from starting
# if libs are not installed
class
ComputeNode
:
def
__init__
(
self
):
raise
ImportError
class
SlapComputePartition
:
def
__init__
(
self
):
raise
ImportError
class
SoftwareInstance
:
def
__init__
(
self
):
raise
ImportError
class
SoftwareRelease
:
def
__init__
(
self
):
raise
ImportError
def
dict2xml
(
dictionary
):
raise
ImportError
def
xml2dict
(
dictionary
):
raise
ImportError
def
calculate_dict_hash
(
dictionary
):
raise
ImportError
def
loads
(
*
args
):
...
...
@@ -118,6 +101,15 @@ def convertToREST(function):
wrapper
.
__doc__
=
function
.
__doc__
return
wrapper
def
castToStr
(
dict_kw
):
instance
=
etree
.
Element
(
'instance'
)
for
_id
,
_value
in
dict_kw
.
iteritems
():
# cast everything to string
etree
.
SubElement
(
instance
,
"parameter"
,
attrib
=
{
'id'
:
_id
}).
text
=
str
(
_value
)
return
etree
.
tostring
(
instance
,
pretty_print
=
True
,
xml_declaration
=
True
,
encoding
=
'utf-8'
)
def
_assertACI
(
document
):
sm
=
getSecurityManager
()
...
...
@@ -162,194 +154,6 @@ class SlapTool(BaseTool):
# Public GET methods
####################################################
def
_isTestRun
(
self
):
if
self
.
REQUEST
.
get
(
'disable_isTestRun'
,
False
):
return
False
if
issubclass
(
self
.
getPortalObject
().
MailHost
.
__class__
,
DummyMailHostMixin
)
\
or
self
.
REQUEST
.
get
(
'test_list'
):
return
True
return
False
def
_getCachePlugin
(
self
):
return
self
.
getPortalObject
().
portal_caches
\
.
getRamCacheRoot
().
get
(
'compute_node_information_cache_factory'
)
\
.
getCachePluginList
()[
0
]
def
_getCacheComputeNodeInformation
(
self
,
compute_node_id
,
user
):
self
.
REQUEST
.
response
.
setHeader
(
'Content-Type'
,
'text/xml; charset=utf-8'
)
slap_compute_node
=
ComputeNode
(
compute_node_id
.
decode
(
"UTF-8"
))
parent_uid
=
self
.
_getComputeNodeUidByReference
(
compute_node_id
)
slap_compute_node
.
_computer_partition_list
=
[]
slap_compute_node
.
_software_release_list
=
\
self
.
_getSoftwareReleaseValueListForComputeNode
(
compute_node_id
)
unrestrictedSearchResults
=
self
.
getPortalObject
().
portal_catalog
.
unrestrictedSearchResults
compute_partition_list
=
unrestrictedSearchResults
(
parent_uid
=
parent_uid
,
validation_state
=
"validated"
,
portal_type
=
"Compute Partition"
)
self
.
_calculateSlapComputeNodeInformation
(
slap_compute_node
,
compute_partition_list
)
return
dumps
(
slap_compute_node
)
def
_fillComputeNodeInformationCache
(
self
,
compute_node_id
,
user
):
key
=
'%s_%s'
%
(
compute_node_id
,
user
)
try
:
self
.
_getCachePlugin
().
set
(
key
,
DEFAULT_CACHE_SCOPE
,
dict
(
time
=
time
.
time
(),
refresh_etag
=
self
.
_calculateRefreshEtag
(),
data
=
self
.
_getCacheComputeNodeInformation
(
compute_node_id
,
user
),
),
cache_duration
=
self
.
getPortalObject
().
portal_caches
\
.
getRamCacheRoot
().
get
(
'compute_node_information_cache_factory'
\
).
cache_duration
)
except
(
Unauthorized
,
IndexError
):
# XXX: Unauthorized hack. Race condition of not ready setup delivery which provides
# security information shall not make this method fail, as it will be
# called later anyway
# Note: IndexError ignored, as it happend in case if full reindex is
# called on site
pass
def
_activateFillComputeNodeInformationCache
(
self
,
compute_node_id
,
user
):
tag
=
'compute_node_information_cache_fill_%s_%s'
%
(
compute_node_id
,
user
)
if
self
.
getPortalObject
().
portal_activities
.
countMessageWithTag
(
tag
)
==
0
:
self
.
activate
(
activity
=
'SQLQueue'
,
tag
=
tag
).
_fillComputeNodeInformationCache
(
compute_node_id
,
user
)
def
_calculateSlapComputeNodeInformation
(
self
,
slap_compute_node
,
compute_partition_list
):
if
len
(
compute_partition_list
)
==
0
:
return
unrestrictedSearchResults
=
self
.
getPortalObject
().
portal_catalog
.
unrestrictedSearchResults
compute_partition_uid_list
=
[
x
.
uid
for
x
in
compute_partition_list
]
grouped_software_instance_list
=
unrestrictedSearchResults
(
portal_type
=
"Software Instance"
,
default_aggregate_uid
=
compute_partition_uid_list
,
validation_state
=
"validated"
,
group_by_list
=
[
'default_aggregate_uid'
],
select_list
=
[
'default_aggregate_uid'
,
'count(*)'
]
)
slave_software_instance_list
=
unrestrictedSearchResults
(
default_aggregate_uid
=
compute_partition_uid_list
,
portal_type
=
'Slave Instance'
,
validation_state
=
"validated"
,
select_list
=
[
'default_aggregate_uid'
],
**
{
"slapos_item.slap_state"
:
"start_requested"
}
)
for
compute_partition
in
compute_partition_list
:
software_instance_list
=
[
x
for
x
in
grouped_software_instance_list
if
(
x
.
default_aggregate_uid
==
compute_partition
.
getUid
())]
if
(
len
(
software_instance_list
)
==
1
)
and
(
software_instance_list
[
0
][
'count(*)'
]
>
1
):
software_instance_list
=
software_instance_list
+
software_instance_list
slap_compute_node
.
_computer_partition_list
.
append
(
self
.
_getSlapPartitionByPackingList
(
_assertACI
(
compute_partition
.
getObject
()),
software_instance_list
,
[
x
for
x
in
slave_software_instance_list
if
(
x
.
default_aggregate_uid
==
compute_partition
.
getUid
())]
)
)
def
_calculateRefreshEtag
(
self
):
# check max indexation timestamp
# it is unlikely to get an empty catalog
last_indexed_entry
=
self
.
getPortalObject
().
portal_catalog
(
select_list
=
[
'indexation_timestamp'
],
portal_type
=
[
'Compute Node'
,
'Compute Partition'
,
'Software Instance'
,
'Slave Instance'
,
'Software Installation'
],
sort_on
=
[(
'indexation_timestamp'
,
'DESC'
)],
limit
=
1
,
)[
0
]
return
'%s_%s'
%
(
last_indexed_entry
.
uid
,
last_indexed_entry
.
indexation_timestamp
)
def
_getComputeNodeInformation
(
self
,
compute_node_id
,
user
,
refresh_etag
):
portal
=
self
.
getPortalObject
()
user_document
=
_assertACI
(
portal
.
portal_catalog
.
unrestrictedGetResultValue
(
reference
=
user
,
portal_type
=
[
'Person'
,
'Compute Node'
,
'Software Instance'
]))
user_type
=
user_document
.
getPortalType
()
self
.
REQUEST
.
response
.
setHeader
(
'Content-Type'
,
'text/xml; charset=utf-8'
)
slap_compute_node
=
ComputeNode
(
compute_node_id
.
decode
(
"UTF-8"
))
parent_uid
=
self
.
_getComputeNodeUidByReference
(
compute_node_id
)
slap_compute_node
.
_computer_partition_list
=
[]
if
user_type
in
(
'Compute Node'
,
'Person'
):
if
not
self
.
_isTestRun
():
cache_plugin
=
self
.
_getCachePlugin
()
key
=
'%s_%s'
%
(
compute_node_id
,
user
)
try
:
entry
=
cache_plugin
.
get
(
key
,
DEFAULT_CACHE_SCOPE
)
except
KeyError
:
entry
=
None
if
entry
is
not
None
and
isinstance
(
entry
.
getValue
(),
dict
):
cached_dict
=
entry
.
getValue
()
cached_etag
=
cached_dict
.
get
(
'refresh_etag'
,
None
)
if
(
refresh_etag
!=
cached_etag
):
# Do not recalculate the compute_node information
# if nothing changed
self
.
_activateFillComputeNodeInformationCache
(
compute_node_id
,
user
)
return
cached_dict
[
'data'
],
cached_etag
else
:
self
.
_activateFillComputeNodeInformationCache
(
compute_node_id
,
user
)
self
.
REQUEST
.
response
.
setStatus
(
503
)
return
self
.
REQUEST
.
response
,
None
else
:
return
self
.
_getCacheComputeNodeInformation
(
compute_node_id
,
user
),
None
else
:
slap_compute_node
.
_software_release_list
=
[]
if
user_type
==
'Software Instance'
:
compute_node
=
self
.
getPortalObject
().
portal_catalog
.
unrestrictedSearchResults
(
portal_type
=
'Compute Node'
,
reference
=
compute_node_id
,
validation_state
=
"validated"
)[
0
].
getObject
()
compute_partition_list
=
compute_node
.
contentValues
(
portal_type
=
"Compute Partition"
,
checked_permission
=
"View"
)
else
:
compute_partition_list
=
self
.
getPortalObject
().
portal_catalog
.
unrestrictedSearchResults
(
parent_uid
=
parent_uid
,
validation_state
=
"validated"
,
portal_type
=
"Compute Partition"
)
self
.
_calculateSlapComputeNodeInformation
(
slap_compute_node
,
compute_partition_list
)
return
dumps
(
slap_compute_node
),
None
@
UnrestrictedMethod
def
_getInstanceTreeIpList
(
self
,
compute_node_id
,
compute_partition_id
):
software_instance
=
self
.
_getSoftwareInstanceForComputePartition
(
compute_node_id
,
compute_partition_id
)
if
software_instance
is
None
or
\
software_instance
.
getSlapState
()
==
'destroy_requested'
:
return
dumps
([])
# Search instance tree
hosting
=
software_instance
.
getSpecialiseValue
()
while
hosting
and
hosting
.
getPortalType
()
!=
"Instance Tree"
:
hosting
=
hosting
.
getSpecialiseValue
()
ip_address_list
=
[]
for
instance
in
hosting
.
getSpecialiseRelatedValueList
(
portal_type
=
"Software Instance"
):
compute_partition
=
instance
.
getAggregateValue
(
portal_type
=
"Compute Partition"
)
if
not
compute_partition
:
continue
for
internet_protocol_address
in
compute_partition
.
contentValues
(
portal_type
=
'Internet Protocol Address'
):
ip_address_list
.
append
(
(
internet_protocol_address
.
getNetworkInterface
(
''
).
decode
(
"UTF-8"
),
internet_protocol_address
.
getIpAddress
().
decode
(
"UTF-8"
))
)
return
dumps
(
ip_address_list
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getFullComputerInformation'
)
def
getFullComputerInformation
(
self
,
computer_id
):
...
...
@@ -362,9 +166,16 @@ class SlapTool(BaseTool):
user
=
self
.
getPortalObject
().
portal_membership
.
getAuthenticatedMember
().
getUserName
()
if
str
(
user
)
==
computer_id
:
compute_node
=
self
.
getPortalObject
().
portal_membership
.
getAuthenticatedMember
().
getUserValue
()
compute_node
.
setAccessStatus
(
'#access %s'
%
computer_id
)
refresh_etag
=
self
.
_calculateRefreshEtag
()
body
,
etag
=
self
.
_getComputeNodeInformation
(
computer_id
,
user
,
refresh_etag
)
compute_node
.
setAccessStatus
(
computer_id
)
else
:
# Don't use getDocument because we don't want use _assertACI here, but
# just call the API on computer.
compute_node
=
self
.
getPortalObject
().
portal_catalog
.
unrestrictedSearchResults
(
portal_type
=
'Compute Node'
,
reference
=
computer_id
,
validation_state
=
"validated"
)[
0
].
getObject
()
refresh_etag
=
compute_node
.
_calculateRefreshEtag
()
body
,
etag
=
compute_node
.
_getComputeNodeInformation
(
user
,
refresh_etag
)
if
self
.
REQUEST
.
response
.
getStatus
()
==
200
:
# Keep in cache server for 7 days
...
...
@@ -386,8 +197,12 @@ class SlapTool(BaseTool):
Search and return all Compute Partition IP address related to one
Instance Tree
"""
result
=
self
.
_getInstanceTreeIpList
(
computer_id
,
computer_partition_id
)
software_instance
=
self
.
_getSoftwareInstanceForComputePartition
(
computer_id
,
computer_partition_id
)
if
software_instance
is
not
None
:
result
=
software_instance
.
_getInstanceTreeIpList
()
else
:
result
=
[]
if
self
.
REQUEST
.
response
.
getStatus
()
==
200
:
# Keep in cache server for 7 days
...
...
@@ -396,7 +211,7 @@ class SlapTool(BaseTool):
self
.
REQUEST
.
response
.
setHeader
(
'Vary'
,
'REMOTE_USER'
)
self
.
REQUEST
.
response
.
setHeader
(
'Last-Modified'
,
rfc1123_date
(
DateTime
()))
self
.
REQUEST
.
response
.
setBody
(
result
)
self
.
REQUEST
.
response
.
setBody
(
dumps
(
result
)
)
return
self
.
REQUEST
.
response
else
:
return
result
...
...
@@ -443,15 +258,13 @@ class SlapTool(BaseTool):
else
:
data_dict
=
instance
.
getAccessStatus
()
last_modified
=
rfc1123_date
(
DateTime
())
# Keep in cache server for 7 days
self
.
REQUEST
.
response
.
setStatus
(
200
)
self
.
REQUEST
.
response
.
setHeader
(
'Cache-Control'
,
'public, max-age=60, stale-if-error=604800'
)
self
.
REQUEST
.
response
.
setHeader
(
'Vary'
,
'REMOTE_USER'
)
self
.
REQUEST
.
response
.
setHeader
(
'Last-Modified'
,
last_modified
)
self
.
REQUEST
.
response
.
setHeader
(
'Last-Modified'
,
rfc1123_date
(
DateTime
())
)
self
.
REQUEST
.
response
.
setHeader
(
'Content-Type'
,
'text/xml; charset=utf-8'
)
self
.
REQUEST
.
response
.
setBody
(
dumps
(
data_dict
))
return
self
.
REQUEST
.
response
...
...
@@ -462,22 +275,16 @@ class SlapTool(BaseTool):
"""
Get the connection status of the partition
"""
compute_node
=
self
.
getPortalObject
().
portal_catalog
.
unrestrictedSearchResults
(
portal_type
=
'Compute Node'
,
reference
=
computer_id
,
validation_state
=
"validated"
)[
0
].
getObject
()
# Be sure to prevent accessing information to disallowed users
compute_node
=
_assertACI
(
compute_node
)
compute_node
=
self
.
_getComputeNodeDocument
(
computer_id
)
data_dict
=
compute_node
.
getAccessStatus
()
last_modified
=
rfc1123_date
(
DateTime
())
# Keep in cache server for 7 days
self
.
REQUEST
.
response
.
setStatus
(
200
)
self
.
REQUEST
.
response
.
setHeader
(
'Cache-Control'
,
'public, max-age=60, stale-if-error=604800'
)
self
.
REQUEST
.
response
.
setHeader
(
'Vary'
,
'REMOTE_USER'
)
self
.
REQUEST
.
response
.
setHeader
(
'Last-Modified'
,
last_modified
)
self
.
REQUEST
.
response
.
setHeader
(
'Last-Modified'
,
rfc1123_date
(
DateTime
())
)
self
.
REQUEST
.
response
.
setHeader
(
'Content-Type'
,
'text/xml; charset=utf-8'
)
self
.
REQUEST
.
response
.
setBody
(
dumps
(
data_dict
))
return
self
.
REQUEST
.
response
...
...
@@ -488,15 +295,11 @@ class SlapTool(BaseTool):
"""
Get the connection status of the software installation
"""
compute_node
=
self
.
getPortalObject
().
portal_catalog
.
unrestrictedSearchResults
(
portal_type
=
'Compute Node'
,
reference
=
computer_id
,
validation_state
=
"validated"
)[
0
].
getObject
()
compute_node
=
self
.
_getComputeNodeDocument
(
computer_id
)
# Be sure to prevent accessing information to disallowed users
compute_node
=
_assertACI
(
compute_node
)
try
:
software_installation
=
self
.
_getSoftwareInstallationForComputeNode
(
url
,
compute_node
)
software_installation
=
compute_node
.
_getSoftwareInstallationFromUrl
(
url
)
except
NotFound
:
data_dict
=
self
.
_getAccessStatus
(
None
)
else
:
...
...
@@ -793,7 +596,6 @@ class SlapTool(BaseTool):
Fire up bung on Compute Node
"""
compute_node
=
self
.
_getComputeNodeDocument
(
compute_node_id
)
compute_node
.
setAccessStatus
(
'#error bang'
)
return
compute_node
.
reportComputeNodeBang
(
comment
=
message
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
...
...
@@ -813,20 +615,6 @@ class SlapTool(BaseTool):
compute_node
.
ComputeNode_updateFromDict
(
compute_node_dict
)
return
'Content properly posted.'
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'useComputerPartition'
)
def
useComputerPartition
(
self
,
computer_id
,
computer_partition_id
,
use_string
):
"""Warning : deprecated method."""
compute_node_document
=
self
.
_getComputeNodeDocument
(
computer_id
)
compute_partition_document
=
self
.
_getComputePartitionDocument
(
compute_node_document
.
getReference
(),
computer_partition_id
)
# easy way to start to store usage messages sent by client in related Web
# Page text_content...
self
.
_reportUsage
(
compute_partition_document
,
use_string
)
return
"""Content properly posted.
WARNING : this method is deprecated. Please use useComputer."""
@
convertToREST
def
_generateComputerCertificate
(
self
,
compute_node_id
):
self
.
_getComputeNodeDocument
(
compute_node_id
).
generateCertificate
()
...
...
@@ -862,71 +650,10 @@ class SlapTool(BaseTool):
"""
# Try to get the compute partition to raise an exception if it doesn't
# exist
portal
=
self
.
getPortalObject
()
compute_partition_document
=
self
.
_getComputePartitionDocument
(
computer_reference
,
computer_partition_reference
)
slap_partition
=
SlapComputePartition
(
computer_reference
.
decode
(
"UTF-8"
),
computer_partition_reference
.
decode
(
"UTF-8"
))
slap_partition
.
_software_release_document
=
None
slap_partition
.
_requested_state
=
'destroyed'
slap_partition
.
_need_modification
=
0
software_instance
=
None
if
compute_partition_document
.
getSlapState
()
==
'busy'
:
software_instance_list
=
portal
.
portal_catalog
.
unrestrictedSearchResults
(
portal_type
=
"Software Instance"
,
default_aggregate_uid
=
compute_partition_document
.
getUid
(),
validation_state
=
"validated"
,
limit
=
2
,
)
software_instance_count
=
len
(
software_instance_list
)
if
software_instance_count
==
1
:
software_instance
=
_assertACI
(
software_instance_list
[
0
].
getObject
())
elif
software_instance_count
>
1
:
# XXX do not prevent the system to work if one partition is broken
raise
NotImplementedError
,
"Too many instances %s linked to %s"
%
\
([
x
.
path
for
x
in
software_instance_list
],
compute_partition_document
.
getRelativeUrl
())
if
software_instance
is
not
None
:
# trick client side, that data has been synchronised already for given
# document
slap_partition
.
_synced
=
True
state
=
software_instance
.
getSlapState
()
if
state
==
"stop_requested"
:
slap_partition
.
_requested_state
=
'stopped'
if
state
==
"start_requested"
:
slap_partition
.
_requested_state
=
'started'
slap_partition
.
_software_release_document
=
SoftwareRelease
(
software_release
=
software_instance
.
getUrlString
().
decode
(
"UTF-8"
),
computer_guid
=
computer_reference
.
decode
(
"UTF-8"
))
slap_partition
.
_need_modification
=
1
parameter_dict
=
self
.
_getSoftwareInstanceAsParameterDict
(
software_instance
)
# software instance has to define an xml parameter
slap_partition
.
_parameter_dict
=
self
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'xml'
))
slap_partition
.
_connection_dict
=
self
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'connection_xml'
))
slap_partition
.
_filter_dict
=
self
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'filter_xml'
))
slap_partition
.
_instance_guid
=
parameter_dict
.
pop
(
'instance_guid'
)
for
slave_instance_dict
in
parameter_dict
.
get
(
"slave_instance_list"
,
[]):
if
slave_instance_dict
.
has_key
(
"connection_xml"
):
connection_dict
=
self
.
_instanceXmlToDict
(
slave_instance_dict
.
pop
(
"connection_xml"
))
slave_instance_dict
.
update
(
connection_dict
)
slave_instance_dict
[
'connection-parameter-hash'
]
=
\
calculate_dict_hash
(
connection_dict
)
if
slave_instance_dict
.
has_key
(
"xml"
):
slave_instance_dict
.
update
(
self
.
_instanceXmlToDict
(
slave_instance_dict
.
pop
(
"xml"
)))
slap_partition
.
_parameter_dict
.
update
(
parameter_dict
)
result
=
dumps
(
slap_partition
)
slap_compute_partition
=
compute_partition_document
.
_registerComputePartition
()
# Keep in cache server for 7 days
self
.
REQUEST
.
response
.
setStatus
(
200
)
...
...
@@ -936,7 +663,7 @@ class SlapTool(BaseTool):
'REMOTE_USER'
)
self
.
REQUEST
.
response
.
setHeader
(
'Last-Modified'
,
rfc1123_date
(
DateTime
()))
self
.
REQUEST
.
response
.
setHeader
(
'Content-Type'
,
'text/xml; charset=utf-8'
)
self
.
REQUEST
.
response
.
setBody
(
result
)
self
.
REQUEST
.
response
.
setBody
(
dumps
(
slap_compute_partition
)
)
return
self
.
REQUEST
.
response
...
...
@@ -966,77 +693,6 @@ class SlapTool(BaseTool):
return
False
def
_instanceXmlToDict
(
self
,
xml
):
result_dict
=
{}
try
:
result_dict
=
xml2dict
(
xml
)
except
(
etree
.
XMLSchemaError
,
etree
.
XMLSchemaParseError
,
# pylint: disable=catching-non-exception
etree
.
XMLSchemaValidateError
,
etree
.
XMLSyntaxError
):
# pylint: disable=catching-non-exception
LOG
(
'SlapTool'
,
INFO
,
'Issue during parsing xml:'
,
error
=
True
)
return
result_dict
def
_getSlapPartitionByPackingList
(
self
,
compute_partition_document
,
software_instance_list
,
slave_instance_sql_list
):
compute_node
=
compute_partition_document
while
compute_node
.
getPortalType
()
!=
'Compute Node'
:
compute_node
=
compute_node
.
getParentValue
()
compute_node_id
=
compute_node
.
getReference
().
decode
(
"UTF-8"
)
slap_partition
=
SlapComputePartition
(
compute_node_id
,
compute_partition_document
.
getReference
().
decode
(
"UTF-8"
))
slap_partition
.
_software_release_document
=
None
slap_partition
.
_requested_state
=
'destroyed'
slap_partition
.
_need_modification
=
0
software_instance
=
None
if
compute_partition_document
.
getSlapState
()
==
'busy'
:
software_instance_count
=
len
(
software_instance_list
)
if
software_instance_count
==
1
:
software_instance
=
_assertACI
(
software_instance_list
[
0
].
getObject
())
elif
software_instance_count
>
1
:
# XXX do not prevent the system to work if one partition is broken
raise
NotImplementedError
,
"Too many instances linked to %s"
%
\
compute_partition_document
.
getRelativeUrl
()
if
software_instance
is
not
None
:
state
=
software_instance
.
getSlapState
()
if
state
==
"stop_requested"
:
slap_partition
.
_requested_state
=
'stopped'
if
state
==
"start_requested"
:
slap_partition
.
_requested_state
=
'started'
slap_partition
.
_access_status
=
software_instance
.
getTextAccessStatus
()
slap_partition
.
_software_release_document
=
SoftwareRelease
(
software_release
=
software_instance
.
getUrlString
().
decode
(
"UTF-8"
),
computer_guid
=
compute_node_id
)
slap_partition
.
_need_modification
=
1
parameter_dict
=
self
.
_getSoftwareInstanceAsParameterDict
(
software_instance
,
slave_instance_sql_list
=
slave_instance_sql_list
)
# software instance has to define an xml parameter
slap_partition
.
_parameter_dict
=
self
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'xml'
))
slap_partition
.
_connection_dict
=
self
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'connection_xml'
))
slap_partition
.
_filter_dict
=
self
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'filter_xml'
))
slap_partition
.
_instance_guid
=
parameter_dict
.
pop
(
'instance_guid'
)
for
slave_instance_dict
in
parameter_dict
.
get
(
"slave_instance_list"
,
[]):
if
slave_instance_dict
.
has_key
(
"connection_xml"
):
slave_instance_dict
.
update
(
self
.
_instanceXmlToDict
(
slave_instance_dict
.
pop
(
"connection_xml"
)))
if
slave_instance_dict
.
has_key
(
"xml"
):
slave_instance_dict
.
update
(
self
.
_instanceXmlToDict
(
slave_instance_dict
.
pop
(
"xml"
)))
slap_partition
.
_parameter_dict
.
update
(
parameter_dict
)
return
slap_partition
@
convertToREST
def
_supplySupply
(
self
,
url
,
compute_node_id
,
state
):
"""
...
...
@@ -1050,31 +706,28 @@ class SlapTool(BaseTool):
"""
Log the software release status
"""
compute_node_document
=
self
.
_getComputeNodeDocument
(
compute_node_id
)
software_installation
=
self
.
_getSoftwareInstallationForComputeNode
(
url
,
compute_node_document
)
software_installation
.
setAccessStatus
(
'#building software release %s'
%
url
,
"building"
)
compute_node
=
self
.
_getComputeNodeDocument
(
compute_node_id
)
software_installation
=
compute_node
.
_getSoftwareInstallationFromUrl
(
url
)
software_installation
.
setBuildingStatus
(
'software release %s'
%
url
,
"building"
)
@
convertToREST
def
_availableSoftwareRelease
(
self
,
url
,
compute_node_id
):
"""
Log the software release status
"""
compute_node_document
=
self
.
_getComputeNodeDocument
(
compute_node_id
)
software_installation
=
self
.
_getSoftwareInstallationForComputeNode
(
url
,
compute_node_document
)
compute_node
=
self
.
_getComputeNodeDocument
(
compute_node_id
)
software_installation
=
compute_node
.
_getSoftwareInstallationFromUrl
(
url
)
software_installation
.
setAccessStatus
(
'
#access
software release %s available'
%
url
,
"available"
)
'software release %s available'
%
url
,
"available"
)
@
convertToREST
def
_destroyedSoftwareRelease
(
self
,
url
,
compute_node_id
):
"""
Reports that Software Release is destroyed
"""
compute_node_document
=
self
.
_getComputeNodeDocument
(
compute_node_id
)
software_installation
=
self
.
_getSoftwareInstallationForComputeNode
(
url
,
compute_node_document
)
compute_node
=
self
.
_getComputeNodeDocument
(
compute_node_id
)
software_installation
=
compute_node
.
_getSoftwareInstallationFromUrl
(
url
)
if
software_installation
.
getSlapState
()
!=
'destroy_requested'
:
raise
NotFound
if
self
.
getPortalObject
().
portal_workflow
.
isTransitionPossible
(
software_installation
,
...
...
@@ -1088,18 +741,14 @@ class SlapTool(BaseTool):
"""
Add an error for the software Instance Workflow
"""
if
error_log
is
None
:
error_log
=
""
instance
=
self
.
_getSoftwareInstanceForComputePartition
(
compute_node_id
,
compute_partition_id
)
status_changed
=
instance
.
setAccessStatus
(
'#error while instanciating: %s'
%
error_log
[
-
80
:])
if
status_changed
:
instance
.
reindexObject
()
if
error_log
is
None
:
error_log
=
""
instance
.
setErrorStatus
(
'while instanciating: %s'
%
error_log
[
-
80
:],
reindex
=
1
)
@
convertToREST
def
_softwareInstanceRename
(
self
,
new_name
,
compute_node_id
,
...
...
@@ -1107,11 +756,7 @@ class SlapTool(BaseTool):
software_instance
=
self
.
_getSoftwareInstanceForComputePartition
(
compute_node_id
,
compute_partition_id
,
slave_reference
)
hosting
=
software_instance
.
getSpecialise
()
for
name
in
[
software_instance
.
getTitle
(),
new_name
]:
# reset request cache
key
=
'_'
.
join
([
hosting
,
name
])
software_instance
.
setLastData
({},
key
=
key
)
return
software_instance
.
rename
(
new_name
=
new_name
,
comment
=
"Rename %s into %s"
%
(
software_instance
.
title
,
new_name
))
...
...
@@ -1126,16 +771,12 @@ class SlapTool(BaseTool):
compute_node_id
,
compute_partition_id
)
software_instance
.
set
AccessStatus
(
'#error
bang called'
)
software_instance
.
set
ErrorStatus
(
'
bang called'
)
timestamp
=
str
(
int
(
software_instance
.
getModificationDate
()))
key
=
"%s_bangstamp"
%
software_instance
.
getReference
()
self
.
getPortalObject
().
portal_workflow
.
getInfoFor
(
software_instance
,
'action'
,
wf_id
=
'instance_slap_interface_workflow'
)
if
(
software_instance
.
getLastData
(
key
)
!=
timestamp
):
if
not
software_instance
.
isLastData
(
key
,
timestamp
):
software_instance
.
bang
(
bang_tree
=
True
,
comment
=
message
)
software_instance
.
setLastData
(
key
,
str
(
int
(
software_instance
.
getModificationDate
())))
return
"OK"
@
convertToREST
...
...
@@ -1146,9 +787,9 @@ class SlapTool(BaseTool):
instance
=
self
.
_getSoftwareInstanceForComputePartition
(
compute_node_id
,
compute_partition_id
)
status_changed
=
instance
.
setAccessStatus
(
'#access Instance correctly started'
,
"started"
)
i
f
status_changed
:
instance
.
reindexObject
(
)
i
nstance
.
setAccessStatus
(
'Instance correctly started'
,
"started"
,
reindex
=
1
)
@
convertToREST
def
_stoppedComputePartition
(
self
,
compute_node_id
,
compute_partition_id
):
...
...
@@ -1158,9 +799,8 @@ class SlapTool(BaseTool):
instance
=
self
.
_getSoftwareInstanceForComputePartition
(
compute_node_id
,
compute_partition_id
)
status_changed
=
instance
.
setAccessStatus
(
'#access Instance correctly stopped'
,
"stopped"
)
if
status_changed
:
instance
.
reindexObject
()
instance
.
setAccessStatus
(
'Instance correctly stopped'
,
"stopped"
,
reindex
=
1
)
@
convertToREST
def
_destroyedComputePartition
(
self
,
compute_node_id
,
compute_partition_id
):
...
...
@@ -1170,30 +810,13 @@ class SlapTool(BaseTool):
instance
=
self
.
_getSoftwareInstanceForComputePartition
(
compute_node_id
,
compute_partition_id
)
if
instance
.
getSlapState
()
==
'destroy_requested'
:
# remove certificate from SI
if
instance
.
getSslKey
()
is
not
None
or
instance
.
getSslCertificate
()
is
not
None
:
instance
.
edit
(
ssl_key
=
None
,
ssl_certificate
=
None
,
)
instance
.
revokeCertificate
()
if
instance
.
getValidationState
()
==
'validated'
:
instance
.
invalidate
()
# XXX Integrate with REST API
# Code duplication will be needed until SlapTool is removed
# revoke certificate
portal
=
self
.
getPortalObject
()
try
:
portal
.
portal_certificate_authority
\
.
revokeCertificate
(
instance
.
getDestinationReference
())
except
ValueError
:
# Ignore already revoked certificates, as OpenSSL backend is
# non transactional, so it is ok to allow multiple tries to destruction
# even if certificate was already revoked
pass
@
convertToREST
def
_setComputePartitionConnectionXml
(
self
,
compute_node_id
,
compute_partition_id
,
...
...
@@ -1207,11 +830,11 @@ class SlapTool(BaseTool):
compute_partition_id
,
slave_reference
)
connection_xml
=
dict2xml
(
loads
(
connection_xml
))
if
software_instance
.
getLastData
()
!=
connection_xml
:
if
not
software_instance
.
isLastData
(
value
=
connection_xml
)
:
software_instance
.
updateConnection
(
connection_xml
=
connection_xml
,
)
software_instance
.
setLastData
(
connection_xml
)
@
convertToREST
def
_requestComputePartition
(
self
,
compute_node_id
,
compute_partition_id
,
...
...
@@ -1248,85 +871,51 @@ class SlapTool(BaseTool):
else
:
filter_kw
=
dict
()
instance
=
etree
.
Element
(
'instance'
)
for
parameter_id
,
parameter_value
in
partition_parameter_kw
.
iteritems
():
# cast everything to string
parameter_value
=
str
(
parameter_value
)
etree
.
SubElement
(
instance
,
"parameter"
,
attrib
=
{
'id'
:
parameter_id
}).
text
=
parameter_value
instance_xml
=
etree
.
tostring
(
instance
,
pretty_print
=
True
,
xml_declaration
=
True
,
encoding
=
'utf-8'
)
instance
=
etree
.
Element
(
'instance'
)
for
parameter_id
,
parameter_value
in
filter_kw
.
iteritems
():
# cast everything to string
parameter_value
=
str
(
parameter_value
)
etree
.
SubElement
(
instance
,
"parameter"
,
attrib
=
{
'id'
:
parameter_id
}).
text
=
parameter_value
sla_xml
=
etree
.
tostring
(
instance
,
pretty_print
=
True
,
xml_declaration
=
True
,
encoding
=
'utf-8'
)
kw
=
dict
(
software_release
=
software_release
,
software_type
=
software_type
,
software_title
=
partition_reference
,
instance_xml
=
castToStr
(
partition_parameter_kw
),
shared
=
shared
,
sla_xml
=
castToStr
(
filter_kw
),
state
=
state
)
portal
=
self
.
getPortalObject
()
if
compute_node_id
and
compute_partition_id
:
# requested by Software Instance, there is already top part of tree
software_instance_document
=
self
.
\
requester
=
self
.
\
_getSoftwareInstanceForComputePartition
(
compute_node_id
,
compute_partition_id
)
instance_tree
=
software_instance_document
.
getSpecialiseValue
()
instance_tree
=
requester
.
getSpecialiseValue
()
if
instance_tree
is
not
None
and
instance_tree
.
getSlapState
()
==
"stop_requested"
:
state
=
'stopped'
kw
=
dict
(
software_release
=
software_release
,
software_type
=
software_type
,
software_title
=
partition_reference
,
instance_xml
=
instance_xml
,
shared
=
shared
,
sla_xml
=
sla_xml
,
state
=
state
)
key
=
'_'
.
join
([
software_instance_document
.
getSpecialise
(),
partition_reference
])
value
=
dict
(
hash
=
'_'
.
join
([
software_instance_document
.
getRelativeUrl
(),
str
(
kw
)]),
)
last_data
=
software_instance_document
.
getLastData
(
key
)
requested_software_instance
=
None
if
last_data
is
not
None
and
isinstance
(
last_data
,
dict
):
requested_software_instance
=
portal
.
restrictedTraverse
(
last_data
.
get
(
'request_instance'
),
None
)
if
last_data
is
None
or
not
isinstance
(
last_data
,
type
(
value
))
or
\
last_data
.
get
(
'hash'
)
!=
value
[
'hash'
]
or
\
requested_software_instance
is
None
:
software_instance_document
.
requestInstance
(
**
kw
)
requested_software_instance
=
self
.
REQUEST
.
get
(
'request_instance'
)
if
requested_software_instance
is
not
None
:
value
[
'request_instance'
]
=
requested_software_instance
\
.
getRelativeUrl
()
software_instance_document
.
setLastData
(
value
,
key
=
key
)
kw
[
'state'
]
=
'stopped'
key
=
'_'
.
join
([
instance_tree
.
getRelativeUrl
(),
partition_reference
])
else
:
# requested as root, so done by human
person
=
portal
.
portal_membership
.
getAuthenticatedMember
().
getUserValue
()
kw
=
dict
(
software_release
=
software_release
,
software_type
=
software_type
,
software_title
=
partition_reference
,
shared
=
shared
,
instance_xml
=
instance_xml
,
sla_xml
=
sla_xml
,
state
=
state
)
key
=
'_'
.
join
([
person
.
getRelativeUrl
(),
partition_reference
])
value
=
dict
(
hash
=
str
(
kw
)
requester
=
portal
.
portal_membership
.
getAuthenticatedMember
().
getUserValue
()
key
=
'_'
.
join
([
requester
.
getRelativeUrl
(),
partition_reference
])
last_data
=
requester
.
getLastData
(
key
)
requested_software_instance
=
None
value
=
dict
(
hash
=
'_'
.
join
([
requester
.
getRelativeUrl
(),
str
(
kw
)]),
)
last_data
=
person
.
getLastData
(
key
)
if
last_data
is
not
None
and
isinstance
(
last_data
,
dict
):
requested_software_instance
=
portal
.
restrictedTraverse
(
if
last_data
is
not
None
and
isinstance
(
last_data
,
type
(
value
)
):
requested_software_instance
=
self
.
restrictedTraverse
(
last_data
.
get
(
'request_instance'
),
None
)
if
last_data
is
None
or
not
isinstance
(
last_data
,
type
(
value
))
or
\
last_data
.
get
(
'hash'
)
!=
value
[
'hash'
]
or
\
requested_software_instance
is
None
:
person
.
requestSoftwareInstance
(
**
kw
)
requested_software_instance
=
self
.
REQUEST
.
get
(
'request_instance'
)
if
requested_software_instance
is
not
None
:
value
[
'request_instance'
]
=
requested_software_instance
\
.
getRelativeUrl
()
requested_software_instance
.
setLastData
(
value
,
key
=
key
)
if
last_data
is
None
or
not
isinstance
(
last_data
,
type
(
value
))
or
\
last_data
.
get
(
'hash'
)
!=
value
[
'hash'
]
or
\
requested_software_instance
is
None
:
if
compute_node_id
and
compute_partition_id
:
requester
.
requestInstance
(
**
kw
)
else
:
# requester is a person so we use another method
requester
.
requestSoftwareInstance
(
**
kw
)
requested_software_instance
=
self
.
REQUEST
.
get
(
'request_instance'
)
if
requested_software_instance
is
not
None
:
value
[
'request_instance'
]
=
requested_software_instance
\
.
getRelativeUrl
()
requester
.
setLastData
(
value
,
key
=
key
)
if
requested_software_instance
is
None
:
raise
SoftwareInstanceNotReady
...
...
@@ -1334,24 +923,7 @@ class SlapTool(BaseTool):
if
not
requested_software_instance
.
getAggregate
(
portal_type
=
"Compute Partition"
):
raise
SoftwareInstanceNotReady
else
:
parameter_dict
=
self
.
_getSoftwareInstanceAsParameterDict
(
requested_software_instance
)
# software instance has to define an xml parameter
xml
=
self
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'xml'
))
connection_xml
=
self
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'connection_xml'
))
filter_xml
=
self
.
_instanceXmlToDict
(
parameter_dict
.
pop
(
'filter_xml'
))
instance_guid
=
parameter_dict
.
pop
(
'instance_guid'
)
software_instance
=
SoftwareInstance
(
**
parameter_dict
)
software_instance
.
_parameter_dict
=
xml
software_instance
.
_connection_dict
=
connection_xml
software_instance
.
_filter_dict
=
filter_xml
software_instance
.
_requested_state
=
state
software_instance
.
_instance_guid
=
instance_guid
return
dumps
(
software_instance
)
return
dumps
(
requested_software_instance
.
_asSoftwareInstance
())
@
UnrestrictedMethod
def
_updateComputePartitionRelatedInstanceList
(
self
,
compute_node_id
,
...
...
@@ -1369,26 +941,7 @@ class SlapTool(BaseTool):
_getSoftwareInstanceForComputePartition
(
compute_node_id
,
compute_partition_id
)
cache_reference
=
'%s-PREDLIST'
%
software_instance_document
.
getReference
()
if
software_instance_document
.
getLastData
(
cache_reference
)
!=
instance_reference_xml
:
instance_reference_list
=
loads
(
instance_reference_xml
)
current_successor_list
=
software_instance_document
.
getSuccessorValueList
(
portal_type
=
[
'Software Instance'
,
'Slave Instance'
])
current_successor_title_list
=
[
i
.
getTitle
()
for
i
in
current_successor_list
]
# If there are items to remove
if
list
(
set
(
current_successor_title_list
).
difference
(
instance_reference_list
))
!=
[]:
successor_list
=
[
instance
.
getRelativeUrl
()
for
instance
in
current_successor_list
if
instance
.
getTitle
()
in
instance_reference_list
]
LOG
(
'SlapTool'
,
INFO
,
'%s, %s: Updating successor list to %s'
%
(
compute_node_id
,
compute_partition_id
,
successor_list
),
error
=
False
)
software_instance_document
.
edit
(
successor_list
=
successor_list
,
comment
=
'successor_list edited to unlink non commited instances'
)
software_instance_document
.
setLastData
(
instance_reference_xml
,
key
=
cache_reference
)
software_instance_document
.
_updateSucessorList
(
instance_reference_xml
)
####################################################
# Internals methods
...
...
@@ -1446,31 +999,6 @@ class SlapTool(BaseTool):
parent_uid
=
self
.
_getComputeNodeUidByReference
(
compute_node_reference
))
def
_getSoftwareInstallationForComputeNode
(
self
,
url
,
compute_node_document
):
software_installation_list
=
self
.
getPortalObject
().
portal_catalog
.
unrestrictedSearchResults
(
portal_type
=
'Software Installation'
,
default_aggregate_uid
=
compute_node_document
.
getUid
(),
validation_state
=
'validated'
,
limit
=
2
,
url_string
=
{
'query'
:
url
,
'key'
:
'ExactMatch'
},
)
l
=
len
(
software_installation_list
)
if
l
==
1
:
return
_assertACI
(
software_installation_list
[
0
].
getObject
())
elif
l
==
0
:
raise
NotFound
(
'No software release %r found on compute_node %r'
%
(
url
,
compute_node_document
.
getReference
()))
else
:
raise
ValueError
(
'Wrong list of software releases on %r: %s'
%
(
compute_node_document
.
getReference
(),
', '
.
join
([
q
.
getRelativeUrl
()
for
q
\
in
software_installation_list
])
))
def
_getSoftwareInstallationReference
(
self
,
url
,
compute_node_document
):
return
self
.
_getSoftwareInstallationForComputeNode
(
url
,
compute_node_document
).
getReference
()
def
_getSoftwareInstanceForComputePartition
(
self
,
compute_node_id
,
compute_partition_id
,
slave_reference
=
None
):
compute_partition_document
=
self
.
_getComputePartitionDocument
(
...
...
@@ -1499,122 +1027,13 @@ class SlapTool(BaseTool):
else
:
return
software_instance
@
UnrestrictedMethod
def
_getSoftwareInstanceAsParameterDict
(
self
,
software_instance
,
slave_instance_sql_list
=
None
):
portal
=
software_instance
.
getPortalObject
()
compute_partition
=
software_instance
.
getAggregateValue
(
portal_type
=
"Compute Partition"
)
timestamp
=
int
(
compute_partition
.
getModificationDate
())
newtimestamp
=
int
(
software_instance
.
getBangTimestamp
(
int
(
software_instance
.
getModificationDate
())))
if
(
newtimestamp
>
timestamp
):
timestamp
=
newtimestamp
instance_tree
=
software_instance
.
getSpecialiseValue
()
ip_list
=
[]
full_ip_list
=
[]
for
internet_protocol_address
in
compute_partition
.
contentValues
(
portal_type
=
'Internet Protocol Address'
):
# XXX - There is new values, and we must keep compatibility
address_tuple
=
(
internet_protocol_address
.
getNetworkInterface
(
''
).
decode
(
"UTF-8"
),
internet_protocol_address
.
getIpAddress
().
decode
(
"UTF-8"
))
if
internet_protocol_address
.
getGatewayIpAddress
(
''
)
and
\
internet_protocol_address
.
getNetmask
(
''
):
address_tuple
=
address_tuple
+
(
internet_protocol_address
.
getGatewayIpAddress
().
decode
(
"UTF-8"
),
internet_protocol_address
.
getNetmask
().
decode
(
"UTF-8"
),
internet_protocol_address
.
getNetworkAddress
(
''
).
decode
(
"UTF-8"
))
full_ip_list
.
append
(
address_tuple
)
else
:
ip_list
.
append
(
address_tuple
)
slave_instance_list
=
[]
if
(
software_instance
.
getPortalType
()
==
"Software Instance"
):
append
=
slave_instance_list
.
append
if
slave_instance_sql_list
is
None
:
slave_instance_sql_list
=
portal
.
portal_catalog
.
unrestrictedSearchResults
(
default_aggregate_uid
=
compute_partition
.
getUid
(),
portal_type
=
'Slave Instance'
,
validation_state
=
"validated"
,
**
{
"slapos_item.slap_state"
:
"start_requested"
}
)
for
slave_instance
in
slave_instance_sql_list
:
slave_instance
=
_assertACI
(
slave_instance
.
getObject
())
# XXX Use catalog to filter more efficiently
if
slave_instance
.
getSlapState
()
==
"start_requested"
:
newtimestamp
=
int
(
slave_instance
.
getBangTimestamp
(
int
(
slave_instance
.
getModificationDate
())))
append
({
'slave_title'
:
slave_instance
.
getTitle
().
decode
(
"UTF-8"
),
'slap_software_type'
:
\
slave_instance
.
getSourceReference
().
decode
(
"UTF-8"
),
'slave_reference'
:
slave_instance
.
getReference
().
decode
(
"UTF-8"
),
'timestamp'
:
newtimestamp
,
'xml'
:
slave_instance
.
getTextContent
(),
'connection_xml'
:
slave_instance
.
getConnectionXml
(),
})
if
(
newtimestamp
>
timestamp
):
timestamp
=
newtimestamp
return
{
'instance_guid'
:
software_instance
.
getReference
().
decode
(
"UTF-8"
),
'instance_title'
:
software_instance
.
getTitle
().
decode
(
"UTF-8"
),
'root_instance_title'
:
instance_tree
.
getTitle
().
decode
(
"UTF-8"
),
'root_instance_short_title'
:
instance_tree
.
getShortTitle
().
decode
(
"UTF-8"
),
'xml'
:
software_instance
.
getTextContent
(),
'connection_xml'
:
software_instance
.
getConnectionXml
(),
'filter_xml'
:
software_instance
.
getSlaXml
(),
'slap_computer_id'
:
\
compute_partition
.
getParentValue
().
getReference
().
decode
(
"UTF-8"
),
'slap_computer_partition_id'
:
\
compute_partition
.
getReference
().
decode
(
"UTF-8"
),
'slap_software_type'
:
\
software_instance
.
getSourceReference
().
decode
(
"UTF-8"
),
'slap_software_release_url'
:
\
software_instance
.
getUrlString
().
decode
(
"UTF-8"
),
'slave_instance_list'
:
slave_instance_list
,
'ip_list'
:
ip_list
,
'full_ip_list'
:
full_ip_list
,
'timestamp'
:
"%i"
%
timestamp
,
}
@
UnrestrictedMethod
def
_getSoftwareReleaseValueListForComputeNode
(
self
,
compute_node_reference
):
"""Returns list of Software Releases documentsfor compute_node"""
compute_node_document
=
self
.
_getComputeNodeDocument
(
compute_node_reference
)
portal
=
self
.
getPortalObject
()
software_release_list
=
[]
for
software_installation
in
portal
.
portal_catalog
.
unrestrictedSearchResults
(
portal_type
=
'Software Installation'
,
default_aggregate_uid
=
compute_node_document
.
getUid
(),
validation_state
=
'validated'
,
):
software_installation
=
_assertACI
(
software_installation
.
getObject
())
software_release_response
=
SoftwareRelease
(
software_release
=
software_installation
.
getUrlString
().
decode
(
'UTF-8'
),
computer_guid
=
compute_node_reference
.
decode
(
'UTF-8'
))
if
software_installation
.
getSlapState
()
==
'destroy_requested'
:
software_release_response
.
_requested_state
=
'destroyed'
else
:
software_release_response
.
_requested_state
=
'available'
known_state
=
software_installation
.
getTextAccessStatus
()
if
known_state
.
startswith
(
"#access"
):
software_release_response
.
_known_state
=
'available'
elif
known_state
.
startswith
(
"#building"
):
software_release_response
.
_known_state
=
'building'
else
:
software_release_response
.
_known_state
=
'error'
software_release_list
.
append
(
software_release_response
)
return
software_release_list
@
convertToREST
def
_softwareReleaseError
(
self
,
url
,
compute_node_id
,
error_log
):
"""
Log the compute_node status
"""
compute_node_document
=
self
.
_getComputeNodeDocument
(
compute_node_id
)
software_installation
=
self
.
_getSoftwareInstallationForComputeNode
(
url
,
compute_node_document
)
software_installation
.
setAccessStatus
(
'#error while installing %s'
%
url
)
compute_node
=
self
.
_getComputeNodeDocument
(
compute_node_id
)
software_installation
=
compute_node
.
_getSoftwareInstallationFromUrl
(
url
)
software_installation
.
setErrorStatus
(
'while installing %s'
%
url
)
InitializeClass
(
SlapTool
)
master/bt5/slapos_slap_tool/bt/template_keep_path_list
View file @
88bdb2d7
portal_caches/last_stored_data_cache_factory
portal_caches/last_stored_data_cache_factory/volatile_cache_plugin
\ No newline at end of file
portal_caches/last_stored_data_cache_factory/volatile_cache_plugin
portal_caches/compute_node_information_cache_factory
portal_caches/compute_node_information_cache_factory/persistent_cache_plugin
\ No newline at end of file
master/bt5/slapos_slap_tool/bt/template_path_list
View file @
88bdb2d7
portal_caches/compute_node_information_cache_factory
portal_caches/compute_node_information_cache_factory/persistent_cache_plugin
portal_caches/slap_cache_factory
portal_caches/slap_cache_factory/persistent_cache_plugin
web_site_module/slapos_hateoas
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment