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
Léo-Paul Géneau
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