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
90a7f4a7
Commit
90a7f4a7
authored
Jul 15, 2022
by
Cédric Le Ninivin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
slapos: Update slapgrid to use new API
parent
8652fba3
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
857 additions
and
279 deletions
+857
-279
slapos/grid/SlapObject.py
slapos/grid/SlapObject.py
+20
-14
slapos/grid/slapgrid.py
slapos/grid/slapgrid.py
+279
-102
slapos/manager/portredir.py
slapos/manager/portredir.py
+1
-2
slapos/slap/slap.py
slapos/slap/slap.py
+31
-1
slapos/tests/test_slapgrid.py
slapos/tests/test_slapgrid.py
+526
-160
No files found.
slapos/grid/SlapObject.py
View file @
90a7f4a7
...
...
@@ -423,6 +423,7 @@ class Partition(object):
instance_storage_home
=
''
,
ipv4_global_network
=
''
,
buildout_debug
=
False
,
api_backward_compatibility
=
False
,
):
"""Initialisation of class parameters"""
self
.
buildout
=
buildout
...
...
@@ -443,6 +444,7 @@ class Partition(object):
self
.
software_release_url
=
software_release_url
self
.
instance_storage_home
=
instance_storage_home
self
.
ipv4_global_network
=
ipv4_global_network
self
.
api_backward_compatibility
=
api_backward_compatibility
self
.
key_file
=
''
self
.
cert_file
=
''
...
...
@@ -489,16 +491,20 @@ class Partition(object):
# Certificate files are unset, skip.
return
try
:
partition_certificate
=
self
.
computer_partition
.
getCertificate
()
except
NotFoundError
:
raise
NotFoundError
(
'Partition %s is not known by SlapOS Master.'
%
self
.
partition_id
)
if
self
.
api_backward_compatibility
:
try
:
partition_certificate
=
self
.
computer_partition
[
"slap_partition"
].
getCertificate
()
self
.
computer_partition
[
"X509"
]
=
{}
self
.
computer_partition
[
"X509"
][
"certificate"
]
=
partition_certificate
[
"certificate"
]
self
.
computer_partition
[
"X509"
][
"key"
]
=
partition_certificate
[
"key"
]
except
NotFoundError
:
raise
NotFoundError
(
'Partition %s is not known by SlapOS Master.'
%
self
.
partition_id
)
uid
,
gid
=
self
.
getUserGroupId
()
for
name
,
path
in
[(
'certificate'
,
self
.
cert_file
),
(
'key'
,
self
.
key_file
)]:
new_content
=
partition_certificate
[
name
]
new_content
=
self
.
computer_partition
[
"X509"
]
[
name
]
old_content
=
None
if
os
.
path
.
exists
(
path
):
old_content
=
open
(
path
).
read
()
...
...
@@ -582,7 +588,7 @@ class Partition(object):
installs the software partition with the help of buildout
"""
self
.
logger
.
info
(
"Installing Computer Partition %s..."
%
self
.
computer_partition
.
get
Id
(
))
%
self
.
computer_partition
.
get
(
"compute_partition_id"
))
self
.
check_free_space
()
...
...
@@ -731,7 +737,7 @@ class Partition(object):
if
os
.
path
.
exists
(
self
.
supervisord_partition_configuration_path
):
os
.
unlink
(
self
.
supervisord_partition_configuration_path
)
else
:
partition_id
=
self
.
computer_partition
.
get
Id
(
)
partition_id
=
self
.
computer_partition
.
get
(
"compute_partition_id"
)
group_partition_template
=
bytes2str
(
pkg_resources
.
resource_string
(
__name__
,
'templates/group_partition_supervisord.conf.in'
))
self
.
supervisor_configuration_group
=
group_partition_template
%
{
...
...
@@ -766,22 +772,22 @@ class Partition(object):
"""Asks supervisord to start the instance. If this instance is not
installed, we install it.
"""
partition_id
=
self
.
computer_partition
.
get
Id
(
)
partition_id
=
self
.
computer_partition
.
get
(
"compute_partition_id"
)
try
:
with
self
.
getSupervisorRPC
()
as
supervisor
:
supervisor
.
startProcessGroup
(
partition_id
,
False
)
except
xmlrpclib
.
Fault
as
exc
:
if
exc
.
faultString
.
startswith
(
'BAD_NAME:'
):
self
.
logger
.
info
(
"Nothing to start on %s..."
%
self
.
computer_partition
.
get
Id
(
))
self
.
computer_partition
.
get
(
"compute_partition_id"
))
else
:
raise
else
:
self
.
logger
.
info
(
"Requested start of %s..."
%
self
.
computer_partition
.
get
Id
(
))
self
.
logger
.
info
(
"Requested start of %s..."
%
self
.
computer_partition
.
get
(
"compute_partition_id"
))
def
stop
(
self
):
"""Asks supervisord to stop the instance."""
partition_id
=
self
.
computer_partition
.
get
Id
(
)
partition_id
=
self
.
computer_partition
.
get
(
"compute_partition_id"
)
try
:
with
self
.
getSupervisorRPC
()
as
supervisor
:
supervisor
.
stopProcessGroup
(
partition_id
,
False
)
...
...
@@ -791,13 +797,13 @@ class Partition(object):
else
:
raise
else
:
self
.
logger
.
info
(
"Requested stop of %s..."
%
self
.
computer_partition
.
get
Id
(
))
self
.
logger
.
info
(
"Requested stop of %s..."
%
self
.
computer_partition
.
get
(
"compute_partition_id"
))
def
destroy
(
self
):
"""Destroys the partition and makes it available for subsequent use."
"""
self
.
logger
.
info
(
"Destroying Computer Partition %s..."
%
self
.
computer_partition
.
get
Id
(
))
%
self
.
computer_partition
.
get
(
"compute_partition_id"
))
self
.
createRetentionLockDate
()
if
not
self
.
checkRetentionIsAuthorized
():
...
...
slapos/grid/slapgrid.py
View file @
90a7f4a7
...
...
@@ -366,6 +366,7 @@ class Slapgrid(object):
buildout_debug
=
False
,
shared_part_list
=
''
,
force_stop
=
False
,
slapgrid_jio_uri
=
None
,
):
"""Makes easy initialisation of class parameters"""
# Parses arguments
...
...
@@ -400,10 +401,16 @@ class Slapgrid(object):
self
.
shadir_key_file
=
shadir_key_file
self
.
forbid_supervisord_automatic_launch
=
forbid_supervisord_automatic_launch
self
.
logger
=
logger
self
.
slapgrid_jio_uri
=
slapgrid_jio_uri
# Creates objects from slap module
self
.
slap
=
slapos
.
slap
.
slap
()
self
.
slap
.
initializeConnection
(
self
.
master_url
,
key_file
=
self
.
key_file
,
cert_file
=
self
.
cert_file
,
master_ca_file
=
self
.
master_ca_file
)
cert_file
=
self
.
cert_file
,
master_ca_file
=
self
.
master_ca_file
,
slapgrid_jio_uri
=
self
.
slapgrid_jio_uri
)
if
self
.
slap
.
jio_api_connector
:
self
.
api_backward_compatibility
=
False
else
:
self
.
api_backward_compatibility
=
True
self
.
computer
=
self
.
slap
.
registerComputer
(
self
.
computer_id
)
# Defines all needed paths
self
.
buildout
=
buildout
...
...
@@ -419,6 +426,7 @@ class Slapgrid(object):
if
computer_partition_filter_list
is
not
None
:
self
.
computer_partition_filter_list
=
\
computer_partition_filter_list
.
split
(
","
)
self
.
computer_partition_list
=
None
self
.
maximum_periodicity
=
maximum_periodicity
self
.
software_min_free_space
=
software_min_free_space
self
.
instance_min_free_space
=
instance_min_free_space
...
...
@@ -553,22 +561,62 @@ stderr_logfile_backups=1
launchSupervisord
(
instance_root
=
self
.
instance_root
,
logger
=
self
.
logger
)
def
getComputerPartitionList
(
self
):
try
:
return
self
.
computer
.
getComputerPartitionList
()
except
socket
.
error
as
exc
:
self
.
logger
.
fatal
(
exc
)
raise
if
self
.
computer_partition_list
is
None
:
if
not
self
.
api_backward_compatibility
:
self
.
computer_partition_list
=
self
.
slap
.
jio_api_connector
.
allDocs
({
"portal_type"
:
"Software Instance"
,
"compute_node_id"
:
self
.
computer_id
,
}).
get
(
"result_list"
,
[])
else
:
try
:
slap_partition_list
=
self
.
computer
.
getComputerPartitionList
()
except
socket
.
error
as
exc
:
self
.
logger
.
fatal
(
exc
)
raise
self
.
computer_partition_list
=
[]
for
partition
in
slap_partition_list
:
try
:
software_release_uri
=
partition
.
getSoftwareRelease
().
getURI
()
except
(
NotFoundError
,
TypeError
,
NameError
):
software_release_uri
=
None
self
.
computer_partition_list
.
append
({
"reference"
:
partition
.
_instance_guid
,
"portal_type"
:
"Software Instance"
,
"compute_partition_id"
:
partition
.
getId
(),
"state"
:
partition
.
getState
(),
"software_type"
:
partition
.
getInstanceParameterDict
().
get
(
'slap_software_type'
,
None
),
"parameters"
:
partition
.
getInstanceParameterDict
(),
"instance_processing_timestamp"
:
partition
.
getInstanceParameterDict
().
get
(
"timestamp"
),
"slap_partition"
:
partition
,
"access_status_message"
:
partition
.
getAccessStatus
(),
"software_release_uri"
:
software_release_uri
,
"sla_parameters"
:
getattr
(
partition
,
'_filter_dict'
,
{}),
})
return
self
.
computer_partition_list
def
sendPartitionError
(
self
,
partition
,
error_message
,
logger
=
None
):
if
not
self
.
api_backward_compatibility
:
self
.
slap
.
jio_api_connector
.
put
({
"portal_type"
:
"Software Instance"
,
"reported_state"
:
"error"
,
"status_message"
:
str
(
error_message
),
"reference"
:
partition
.
get
(
"reference"
)
})
else
:
partition
[
"slap_partition"
].
error
(
error_message
,
logger
=
logger
)
def
getRequiredComputerPartitionList
(
self
):
"""Return the computer partitions that should be processed.
"""
cp_list
=
self
.
getComputerPartitionList
()
cp_id_list
=
[
cp
.
get
Id
(
)
for
cp
in
cp_list
]
cp_id_list
=
[
cp
.
get
(
"computer_partition_id"
,
""
)
for
cp
in
cp_list
]
required_cp_id_set
=
check_required_only_partitions
(
cp_id_list
,
self
.
computer_partition_filter_list
)
busy_cp_list
=
self
.
FilterComputerPartitionList
(
cp_list
)
if
required_cp_id_set
:
return
[
cp
for
cp
in
busy_cp_list
if
cp
.
get
Id
(
)
in
required_cp_id_set
]
return
[
cp
for
cp
in
busy_cp_list
if
cp
.
get
(
"computer_partition_id"
,
""
)
in
required_cp_id_set
]
return
busy_cp_list
def
processSoftwareReleaseList
(
self
):
...
...
@@ -578,10 +626,27 @@ stderr_logfile_backups=1
self
.
logger
.
info
(
'Processing software releases...'
)
# Boolean to know if every instance has correctly been deployed
clean_run
=
True
for
software_release
in
self
.
computer
.
getSoftwareReleaseList
():
state
=
software_release
.
getState
()
if
not
self
.
api_backward_compatibility
:
software_installation_list
=
self
.
slap
.
jio_api_connector
.
allDocs
({
"portal_type"
:
"Software Installation"
,
"compute_node_id"
:
self
.
computer_id
})
if
"result_list"
in
software_installation_list
:
software_installation_list
=
software_installation_list
[
"result_list"
]
else
:
software_installation_list
=
[]
else
:
software_installation_list
=
[]
for
software_release
in
self
.
computer
.
getSoftwareReleaseList
():
software_installation_list
.
append
({
"software_release_uri"
:
software_release
.
getURI
(),
"state"
:
software_release
.
getState
(),
"compatibility_software_release"
:
software_release
,
})
for
software_release
in
software_installation_list
:
state
=
software_release
[
"state"
]
try
:
software_release_uri
=
software_release
.
getURI
()
software_release_uri
=
software_release
[
"software_release_uri"
]
url_hash
=
md5digest
(
software_release_uri
)
software_path
=
os
.
path
.
join
(
self
.
software_root
,
url_hash
)
software
=
Software
(
url
=
software_release_uri
,
...
...
@@ -623,7 +688,15 @@ stderr_logfile_backups=1
url_hash
in
self
.
software_release_filter_list
or
url_hash
in
(
md5digest
(
uri
)
for
uri
in
self
.
software_release_filter_list
)):
try
:
software_release
.
building
()
if
not
self
.
api_backward_compatibility
:
self
.
slap
.
jio_api_connector
.
put
({
"portal_type"
:
"Software Installation"
,
"compute_node_id"
:
self
.
computer_id
,
"software_release_uri"
:
software_release_uri
,
"reported_state"
:
"building"
,
})
else
:
software_release
[
"compatibility_software_release"
].
building
()
except
NotFoundError
:
pass
software
.
install
()
...
...
@@ -640,14 +713,32 @@ stderr_logfile_backups=1
manager
.
softwareTearDown
(
software
)
# Send log before exiting
except
(
SystemExit
,
KeyboardInterrupt
):
software_release
.
error
(
traceback
.
format_exc
(),
logger
=
self
.
logger
)
if
not
self
.
api_backward_compatibility
:
self
.
slap
.
jio_api_connector
.
put
({
"portal_type"
:
"Software Installation"
,
"compute_node_id"
:
self
.
computer_id
,
"software_release_uri"
:
software_release_uri
,
"error_status"
:
traceback
.
format_exc
(),
})
else
:
software_release
[
"compatibility_software_release"
].
error
(
traceback
.
format_exc
(),
logger
=
self
.
logger
)
raise
# Buildout failed: send log but don't print it to output (already done)
except
BuildoutFailedError
as
exc
:
clean_run
=
False
try
:
software_release
.
error
(
exc
,
logger
=
self
.
logger
)
if
not
self
.
api_backward_compatibility
:
self
.
slap
.
jio_api_connector
.
put
({
"portal_type"
:
"Software Installation"
,
"compute_node_id"
:
self
.
computer_id
,
"software_release_uri"
:
software_release_uri
,
"error_status"
:
str
(
exc
),
})
else
:
software_release
[
"compatibility_software_release"
].
error
(
exc
,
logger
=
self
.
logger
)
except
(
SystemExit
,
KeyboardInterrupt
):
raise
except
Exception
:
...
...
@@ -656,17 +747,43 @@ stderr_logfile_backups=1
# For everything else: log it, send it, continue.
except
Exception
:
self
.
logger
.
exception
(
''
)
software_release
.
error
(
traceback
.
format_exc
(),
logger
=
self
.
logger
)
if
not
self
.
api_backward_compatibility
:
self
.
slap
.
jio_api_connector
.
put
({
"portal_type"
:
"Software Installation"
,
"compute_node_id"
:
self
.
computer_id
,
"software_release_uri"
:
software_release_uri
,
"error_status"
:
traceback
.
format_exc
(),
})
else
:
software_release
[
"compatibility_software_release"
].
error
(
traceback
.
format_exc
(),
logger
=
self
.
logger
)
clean_run
=
False
else
:
if
state
==
'available'
:
try
:
software_release
.
available
()
if
not
self
.
api_backward_compatibility
:
self
.
slap
.
jio_api_connector
.
put
({
"portal_type"
:
"Software Installation"
,
"compute_node_id"
:
self
.
computer_id
,
"software_release_uri"
:
software_release_uri
,
"reported_state"
:
"available"
,
})
else
:
software_release
[
"compatibility_software_release"
].
available
()
except
(
NotFoundError
,
ServerError
):
pass
elif
state
==
'destroyed'
:
try
:
software_release
.
destroyed
()
if
not
self
.
api_backward_compatibility
:
self
.
slap
.
jio_api_connector
.
put
({
"portal_type"
:
"Software Installation"
,
"compute_node_id"
:
self
.
computer_id
,
"software_release_uri"
:
software_release_uri
,
"reported_state"
:
"destroyed"
,
})
else
:
software_release
[
"compatibility_software_release"
].
destroyed
()
except
(
NotFoundError
,
ServerError
):
self
.
logger
.
exception
(
''
)
self
.
logger
.
info
(
'Finished software releases.'
)
...
...
@@ -764,7 +881,7 @@ stderr_logfile_backups=1
return
PromiseLauncher
(
config
=
promise_config
,
logger
=
self
.
logger
).
run
()
def
_endInstallationTransaction
(
self
,
computer_partition
):
partition_id
=
computer_partition
.
get
Id
(
)
partition_id
=
computer_partition
.
get
(
"compute_partition_id"
)
transaction_file_name
=
COMPUTER_PARTITION_REQUEST_LIST_TEMPLATE_FILENAME
%
partition_id
transaction_file_path
=
os
.
path
.
join
(
self
.
instance_root
,
partition_id
,
...
...
@@ -773,9 +890,16 @@ stderr_logfile_backups=1
if
os
.
path
.
exists
(
transaction_file_path
):
with
open
(
transaction_file_path
,
'r'
)
as
tf
:
try
:
computer_partition
.
setComputerPartitionRelatedInstanceList
(
[
reference
for
reference
in
tf
.
read
().
split
(
'
\
n
'
)
if
reference
]
)
if
not
self
.
api_backward_compatibility
:
self
.
slap
.
jio_api_connector
.
put
({
"portal_type"
:
"Software Instance"
,
"reference"
:
computer_partition
.
get
(
"reference"
),
"requested_instance_list"
:
[
reference
for
reference
in
tf
.
read
().
split
(
'
\
n
'
)
if
reference
],
})
else
:
computer_partition
[
"slap_partition"
].
setComputerPartitionRelatedInstanceList
(
[
reference
for
reference
in
tf
.
read
().
split
(
'
\
n
'
)
if
reference
]
)
except
NotFoundError
as
e
:
# Master doesn't implement this feature ?
self
.
logger
.
warning
(
"NotFoundError: %s.
\
n
Cannot send requested instance "
\
...
...
@@ -986,7 +1110,23 @@ stderr_logfile_backups=1
elif
valid_ipv6
(
ip
):
ipv6_list
.
append
(
ip
)
hosting_ip_list
=
computer_partition
.
getFullHostingIpAddressList
()
if
not
self
.
api_backward_compatibility
:
hosting_ip_list
=
[]
# Get all the instances of the instance tree
related_instance_list
=
self
.
slap
.
jio_api_connector
.
allDocs
({
"portal_type"
:
"Software Instance"
,
"root_instance_title"
:
computer_partition
[
"root_instance_title"
],
}).
get
(
"result_list"
,
[])
for
instance_result
in
related_instance_list
:
if
instance_result
[
"reference"
]
!=
computer_partition
[
"reference"
]:
instance
=
self
.
slap
.
jio_api_connector
.
get
({
"portal_type"
:
"Software Instance"
,
"reference"
:
instance_result
[
"reference"
],
})
hosting_ip_list
=
hosting_ip_list
+
instance
[
"ip_list"
]
else
:
hosting_ip_list
=
computer_partition
[
"slap_partition"
].
getFullHostingIpAddressList
()
for
iface
,
ip
in
hosting_ip_list
:
if
valid_ipv4
(
ip
):
if
not
ip
in
ipv4_list
:
...
...
@@ -995,7 +1135,7 @@ stderr_logfile_backups=1
if
not
ip
in
ipv6_list
:
hosting_ipv6_list
.
append
(
ip
)
filter_dict
=
getattr
(
computer_partition
,
'_filter_dict
'
,
None
)
filter_dict
=
computer_partition
.
get
(
'sla_parameters
'
,
None
)
extra_list
=
[]
accept_ip_list
=
[]
if
filter_dict
is
not
None
:
...
...
@@ -1015,11 +1155,11 @@ stderr_logfile_backups=1
for
ip
in
ipv4_list
:
cmd_list
=
getFirewallRules
(
ip
,
hosting_ipv4_list
,
source_ipv4_list
,
ip_type
=
'ipv4'
)
self
.
_checkAddFirewallRules
(
computer_partition
.
get
Id
(
),
self
.
_checkAddFirewallRules
(
computer_partition
.
get
(
"compute_partition_id"
),
cmd_list
,
add
=
add_rules
)
def
_checkPromiseAnomaly
(
self
,
local_partition
,
computer_partition
):
partition_access_status
=
computer_partition
.
get
AccessStatus
(
)
partition_access_status
=
computer_partition
.
get
(
"access_status_message"
,
""
)
status_error
=
False
if
partition_access_status
and
partition_access_status
.
startswith
(
"#error"
):
status_error
=
True
...
...
@@ -1031,17 +1171,24 @@ stderr_logfile_backups=1
self
.
logger
.
error
(
e
)
if
partition_access_status
is
None
or
not
status_error
:
local_partition
.
_updateCertificate
()
computer_partition
.
error
(
e
,
logger
=
self
.
logger
)
self
.
sendPartitionError
(
computer_partition
,
e
,
logger
=
self
.
logger
)
else
:
if
partition_access_status
is
None
or
status_error
:
local_partition
.
_updateCertificate
()
computer_partition
.
started
()
if
not
self
.
api_backward_compatibility
:
self
.
slap
.
jio_api_connector
.
put
({
"portal_type"
:
"Software Instance"
,
"reference"
:
computer_partition
.
get
(
"reference"
),
"reported_state"
:
"started"
})
else
:
computer_partition
[
"slap_partition"
].
started
()
def
processPromise
(
self
,
computer_partition
):
"""
Process the promises from a given Computer Partition, depending on its state
"""
computer_partition_id
=
computer_partition
.
get
Id
(
)
computer_partition_id
=
computer_partition
.
get
(
"compute_partition_id"
)
# Sanity checks before processing
# Those values should not be None or empty string or any falsy value
...
...
@@ -1050,12 +1197,7 @@ stderr_logfile_backups=1
instance_path
=
os
.
path
.
join
(
self
.
instance_root
,
computer_partition_id
)
os
.
environ
[
'SLAPGRID_INSTANCE_ROOT'
]
=
self
.
instance_root
try
:
software_url
=
computer_partition
.
getSoftwareRelease
().
getURI
()
except
NotFoundError
:
# Problem with instance: SR URI not set.
# Try to process it anyway, it may need to be deleted.
software_url
=
None
software_url
=
computer_partition
.
get
(
"software_release_uri"
)
try
:
software_path
=
os
.
path
.
join
(
self
.
software_root
,
md5digest
(
software_url
))
...
...
@@ -1064,7 +1206,7 @@ stderr_logfile_backups=1
# Try to process it anyway, it may need to be deleted.
software_path
=
None
computer_partition_state
=
computer_partition
.
get
State
(
)
computer_partition_state
=
computer_partition
.
get
(
"state"
)
local_partition
=
Partition
(
software_path
=
software_path
,
...
...
@@ -1082,10 +1224,11 @@ stderr_logfile_backups=1
buildout
=
self
.
buildout
,
buildout_debug
=
self
.
buildout_debug
,
logger
=
self
.
logger
,
retention_delay
=
getattr
(
computer_partition
,
'_filter_dict
'
,
{}).
get
(
'retention_delay'
,
'0'
),
retention_delay
=
computer_partition
.
get
(
'sla_parameters
'
,
{}).
get
(
'retention_delay'
,
'0'
),
instance_min_free_space
=
self
.
instance_min_free_space
,
instance_storage_home
=
self
.
instance_storage_home
,
ipv4_global_network
=
self
.
ipv4_global_network
,
api_backward_compatibility
=
self
.
api_backward_compatibility
,
)
self
.
logger
.
info
(
'Processing Promises for Computer Partition %s.'
,
computer_partition_id
)
...
...
@@ -1101,7 +1244,7 @@ stderr_logfile_backups=1
"""
Process a Computer Partition, depending on its state
"""
computer_partition_id
=
computer_partition
.
get
Id
(
)
computer_partition_id
=
computer_partition
.
get
(
"compute_partition_id"
)
# Sanity checks before processing
# Those values should not be None or empty string or any falsy value
...
...
@@ -1125,20 +1268,14 @@ stderr_logfile_backups=1
instance_path
,
COMPUTER_PARTITION_TIMESTAMP_FILENAME
)
parameter_dict
=
computer_partition
.
getInstanceParameterDict
()
timestamp
=
parameter_dict
.
get
(
'timestamp'
)
timestamp
=
computer_partition
.
get
(
"processing_timestamp"
)
error_output_file
=
os
.
path
.
join
(
instance_path
,
COMPUTER_PARTITION_INSTALL_ERROR_FILENAME
%
computer_partition_id
)
try
:
software_url
=
computer_partition
.
getSoftwareRelease
().
getURI
()
except
NotFoundError
:
# Problem with instance: SR URI not set.
# Try to process it anyway, it may need to be deleted.
software_url
=
None
software_url
=
computer_partition
.
get
(
"software_release_uri"
)
try
:
software_path
=
os
.
path
.
join
(
self
.
software_root
,
md5digest
(
software_url
))
except
TypeError
:
...
...
@@ -1146,7 +1283,7 @@ stderr_logfile_backups=1
# Try to process it anyway, it may need to be deleted.
software_path
=
None
computer_partition_state
=
computer_partition
.
get
State
(
)
computer_partition_state
=
computer_partition
.
get
(
"state"
)
periodicity
=
self
.
maximum_periodicity
if
software_path
:
periodicity_path
=
os
.
path
.
join
(
software_path
,
'periodicity'
)
...
...
@@ -1174,7 +1311,7 @@ stderr_logfile_backups=1
buildout
=
self
.
buildout
,
buildout_debug
=
self
.
buildout_debug
,
logger
=
self
.
logger
,
retention_delay
=
getattr
(
computer_partition
,
'_filter_dict
'
,
{}).
get
(
'retention_delay'
,
'0'
),
retention_delay
=
computer_partition
.
get
(
'sla_parameters
'
,
{}).
get
(
'retention_delay'
,
'0'
),
instance_min_free_space
=
self
.
instance_min_free_space
,
instance_storage_home
=
self
.
instance_storage_home
,
ipv4_global_network
=
self
.
ipv4_global_network
,
...
...
@@ -1254,7 +1391,7 @@ stderr_logfile_backups=1
local_partition
.
_updateCertificate
()
# XXX this line breaks 37 tests
# self.logger.info(' Instance type: %s' % computer_partition.get
Type(
))
# self.logger.info(' Instance type: %s' % computer_partition.get
("software_type"
))
self
.
logger
.
info
(
' Instance status: %s'
%
computer_partition_state
)
if
os
.
path
.
exists
(
error_output_file
):
...
...
@@ -1262,7 +1399,7 @@ stderr_logfile_backups=1
partition_ip_list
=
full_hosting_ip_list
=
[]
if
self
.
firewall_conf
:
partition_ip_list
=
parameter_dict
[
'ip_list'
]
+
parameter_dict
.
get
(
partition_ip_list
=
computer_partition
[
'ip_list'
]
+
computer_partition
.
get
(
'full_ip_list'
,
[])
if
computer_partition_state
==
COMPUTER_PARTITION_STARTED_STATE
:
...
...
@@ -1276,7 +1413,14 @@ stderr_logfile_backups=1
partition_ip_list
)
if
not
self
.
force_stop
:
self
.
_checkPromiseList
(
local_partition
)
computer_partition
.
started
()
if
not
self
.
api_backward_compatibility
:
self
.
slap
.
jio_api_connector
.
put
({
"portal_type"
:
"Software Instance"
,
"reference"
:
computer_partition
.
get
(
"reference"
),
"reported_state"
:
"started"
})
else
:
computer_partition
[
"slap_partition"
].
started
()
self
.
_endInstallationTransaction
(
computer_partition
)
elif
computer_partition_state
==
COMPUTER_PARTITION_STOPPED_STATE
:
try
:
...
...
@@ -1290,9 +1434,16 @@ stderr_logfile_backups=1
# Instance has to be stopped even if buildout/reporting is wrong.
local_partition
.
stop
()
try
:
computer_partition
.
stopped
()
if
not
self
.
api_backward_compatibility
:
self
.
slap
.
jio_api_connector
.
put
({
"portal_type"
:
"Software Instance"
,
"reference"
:
computer_partition
.
get
(
"reference"
),
"reported_state"
:
"stopped"
})
else
:
computer_partition
[
"slap_partition"
].
stopped
()
except
(
SystemExit
,
KeyboardInterrupt
):
computer_partition
.
error
(
traceback
.
format_exc
(),
logger
=
self
.
logger
)
self
.
sendPartitionError
(
computer_partition
,
traceback
.
format_exc
(),
logger
=
self
.
logger
)
raise
except
Exception
:
pass
...
...
@@ -1304,16 +1455,23 @@ stderr_logfile_backups=1
partition_ip_list
,
drop_entries
=
True
)
try
:
computer_partition
.
stopped
()
if
not
self
.
api_backward_compatibility
:
self
.
slap
.
jio_api_connector
.
put
({
"portal_type"
:
"Software Instance"
,
"reference"
:
computer_partition
.
get
(
"reference"
),
"reported_state"
:
"stopped"
})
else
:
computer_partition
[
"slap_partition"
].
stopped
()
except
(
SystemExit
,
KeyboardInterrupt
):
computer_partition
.
error
(
traceback
.
format_exc
(),
logger
=
self
.
logger
)
self
.
sendPartitionError
(
computer_partition
,
traceback
.
format_exc
(),
logger
=
self
.
logger
)
raise
except
Exception
:
pass
else
:
error_string
=
"Computer Partition %r has unsupported state: %s"
%
\
(
computer_partition_id
,
computer_partition_state
)
computer_partition
.
error
(
error_string
,
logger
=
self
.
logger
)
self
.
sendPartitionError
(
computer_partition
,
error_string
,
logger
=
self
.
logger
)
raise
NotImplementedError
(
error_string
)
except
Exception
as
e
:
if
not
isinstance
(
e
,
PromiseError
):
...
...
@@ -1349,7 +1507,7 @@ stderr_logfile_backups=1
for
computer_partition
in
computer_partition_list
:
try
:
computer_partition_path
=
os
.
path
.
join
(
self
.
instance_root
,
computer_partition
.
get
Id
(
))
computer_partition
.
get
(
"compute_partition_id"
))
if
not
os
.
path
.
exists
(
computer_partition_path
):
raise
NotFoundError
(
'Partition directory %s does not exist.'
%
computer_partition_path
)
...
...
@@ -1358,11 +1516,8 @@ stderr_logfile_backups=1
# partition, and check if it has some Software information.
# XXX-Cedric: Temporary AND ugly solution to check if an instance
# is in the partition. Dangerous because not 100% sure it is empty
computer_partition_state
=
computer_partition
.
getState
()
try
:
software_url
=
computer_partition
.
getSoftwareRelease
().
getURI
()
except
(
NotFoundError
,
TypeError
,
NameError
):
software_url
=
None
computer_partition_state
=
computer_partition
.
get
(
"state"
)
software_url
=
computer_partition
.
get
(
"software_release_uri"
)
if
computer_partition_state
==
COMPUTER_PARTITION_DESTROYED_STATE
and
\
not
software_url
:
# Exclude files which may come from concurrent processing
...
...
@@ -1380,7 +1535,7 @@ stderr_logfile_backups=1
# Ignore .slapos-resource file dumped by slapformat.
if
os
.
listdir
(
computer_partition_path
)
not
in
empty_partition_listdir
:
self
.
logger
.
warning
(
"Free partition %s contains file(s) in %s."
%
(
computer_partition
.
get
Id
(
),
computer_partition_path
))
computer_partition
.
get
(
"compute_partition_id"
),
computer_partition_path
))
continue
# Everything seems fine
...
...
@@ -1390,7 +1545,7 @@ stderr_logfile_backups=1
# Send log before exiting
except
(
SystemExit
,
KeyboardInterrupt
):
computer_partition
.
error
(
traceback
.
format_exc
(),
logger
=
self
.
logger
)
self
.
sendPartitionError
(
computer_partition
,
traceback
.
format_exc
(),
logger
=
self
.
logger
)
raise
except
Exception
as
exc
:
...
...
@@ -1399,7 +1554,7 @@ stderr_logfile_backups=1
# For everything else: log it, send it, continue.
self
.
logger
.
exception
(
''
)
try
:
computer_partition
.
error
(
exc
,
logger
=
self
.
logger
)
self
.
sendPartitionError
(
computer_partition
,
exc
,
logger
=
self
.
logger
)
except
(
SystemExit
,
KeyboardInterrupt
):
raise
except
Exception
:
...
...
@@ -1430,20 +1585,25 @@ stderr_logfile_backups=1
# Nothing should raise outside of the current loop iteration, so that
# even if something is terribly wrong while processing an instance, it
# won't prevent processing other ones.
if
not
self
.
api_backward_compatibility
:
computer_partition
=
self
.
slap
.
jio_api_connector
.
get
({
"portal_type"
:
"Software Instance"
,
"reference"
:
computer_partition
[
"reference"
]
})
try
:
# Process the partition itself
self
.
processComputerPartition
(
computer_partition
)
# Send log before exiting
except
(
SystemExit
,
KeyboardInterrupt
):
computer_partition
.
error
(
traceback
.
format_exc
(),
logger
=
self
.
logger
)
self
.
sendPartitionError
(
computer_partition
,
traceback
.
format_exc
(),
logger
=
self
.
logger
)
raise
except
PromiseError
as
exc
:
clean_run_promise
=
False
try
:
self
.
logger
.
error
(
exc
)
computer_partition
.
error
(
exc
,
logger
=
self
.
logger
)
self
.
sendPartitionError
(
computer_partition
,
exc
,
logger
=
self
.
logger
)
promise_error_partition_list
.
append
((
computer_partition
,
exc
))
except
(
SystemExit
,
KeyboardInterrupt
):
raise
...
...
@@ -1457,7 +1617,7 @@ stderr_logfile_backups=1
# For everything else: log it, send it, continue.
self
.
logger
.
exception
(
''
)
try
:
computer_partition
.
error
(
exc
,
logger
=
self
.
logger
)
self
.
sendPartitionError
(
computer_partition
,
exc
,
logger
=
self
.
logger
)
process_error_partition_list
.
append
((
computer_partition
,
exc
))
except
(
SystemExit
,
KeyboardInterrupt
):
raise
...
...
@@ -1467,9 +1627,8 @@ stderr_logfile_backups=1
def
getPartitionType
(
part
):
"""returns the partition type, if known at that point.
"""
try
:
return
part
.
getType
()
except
slapos
.
slap
.
ResourceNotReady
:
software_type
=
partition
.
get
(
"software_type"
,
None
)
if
software_type
is
None
:
return
'(not ready)'
self
.
logger
.
info
(
'Finished computer partitions.'
)
...
...
@@ -1477,11 +1636,11 @@ stderr_logfile_backups=1
if
process_error_partition_list
:
self
.
logger
.
info
(
'Error while processing the following partitions:'
)
for
partition
,
exc
in
process_error_partition_list
:
self
.
logger
.
info
(
' %s[%s]: %s'
,
partition
.
get
Id
(
),
getPartitionType
(
partition
),
exc
)
self
.
logger
.
info
(
' %s[%s]: %s'
,
partition
.
get
(
"compute_partition_id"
),
getPartitionType
(
partition
),
exc
)
if
promise_error_partition_list
:
self
.
logger
.
info
(
'Error with promises for the following partitions:'
)
for
partition
,
exc
in
promise_error_partition_list
:
self
.
logger
.
info
(
' %s[%s]: %s'
,
partition
.
get
Id
(
),
getPartitionType
(
partition
),
exc
)
self
.
logger
.
info
(
' %s[%s]: %s'
,
partition
.
get
(
"compute_partition_id"
),
getPartitionType
(
partition
),
exc
)
# Return success value
if
not
clean_run
:
...
...
@@ -1502,6 +1661,11 @@ stderr_logfile_backups=1
promise_error_partition_list
=
[]
for
computer_partition
in
computer_partition_list
:
if
not
self
.
api_backward_compatibility
:
computer_partition
=
self
.
slap
.
jio_api_connector
.
get
({
"portal_type"
:
"Software Instance"
,
"reference"
:
computer_partition
[
"reference"
]
})
try
:
# Process the partition itself
self
.
processPromise
(
computer_partition
)
...
...
@@ -1517,15 +1681,14 @@ stderr_logfile_backups=1
def
getPartitionType
(
part
):
"""returns the partition type, if known at that point.
"""
try
:
return
part
.
getType
()
except
slapos
.
slap
.
ResourceNotReady
:
software_type
=
partition
.
get
(
"software_type"
,
None
)
if
software_type
is
None
:
return
'(not ready)'
if
promise_error_partition_list
:
self
.
logger
.
info
(
'Finished computer partitions.'
)
for
partition
,
exc
in
promise_error_partition_list
:
self
.
logger
.
info
(
' %s[%s]: %s'
,
partition
.
get
Id
(
),
getPartitionType
(
partition
),
exc
)
self
.
logger
.
info
(
' %s[%s]: %s'
,
partition
.
get
(
"compute_partition_id"
),
getPartitionType
(
partition
),
exc
)
# Return success value
if
not
clean_run_promise
:
...
...
@@ -1618,7 +1781,6 @@ stderr_logfile_backups=1
self
.
checkEnvironmentAndCreateStructure
()
self
.
_launchSupervisord
()
slap_computer_usage
=
self
.
slap
.
registerComputer
(
self
.
computer_id
)
computer_partition_usage_list
=
[]
self
.
logger
.
info
(
'Aggregating and sending usage reports...'
)
...
...
@@ -1648,11 +1810,11 @@ stderr_logfile_backups=1
clean_run
=
True
# Loop over the different computer partitions
computer_partition_list
=
self
.
FilterComputerPartitionList
(
s
lap_computer_usage
.
getComputerPartitionList
())
s
elf
.
getComputerPartitionList
())
for
computer_partition
in
computer_partition_list
:
try
:
computer_partition_id
=
computer_partition
.
get
Id
(
)
computer_partition_id
=
computer_partition
.
get
(
"compute_partition_id"
)
instance_path
=
os
.
path
.
join
(
self
.
instance_root
,
computer_partition_id
)
...
...
@@ -1688,18 +1850,18 @@ stderr_logfile_backups=1
failed_script_list
.
append
(
"Script %r failed."
%
script
)
self
.
logger
.
warning
(
'Failed to run %r'
%
invocation_list
)
if
len
(
failed_script_list
):
computer_partition
.
error
(
'
\
n
'
.
join
(
failed_script_list
),
logger
=
self
.
logger
)
self
.
sendPartitionError
(
computer_partition
,
'
\
n
'
.
join
(
failed_script_list
),
logger
=
self
.
logger
)
# Whatever happens, don't stop processing other instances
except
Exception
:
self
.
logger
.
exception
(
'Cannot run usage script(s) for %r:'
%
computer_partition
.
get
Id
(
))
computer_partition
.
get
(
"compute_partition_id"
))
# Now we loop through the different computer partitions to report
report_usage_issue_cp_list
=
[]
for
computer_partition
in
computer_partition_list
:
try
:
filename_delete_list
=
[]
computer_partition_id
=
computer_partition
.
get
Id
(
)
computer_partition_id
=
computer_partition
.
get
(
"compute_partition_id"
)
instance_path
=
os
.
path
.
join
(
self
.
instance_root
,
computer_partition_id
)
dir_report_list
=
[
os
.
path
.
join
(
instance_path
,
'var'
,
'xml_report'
),
os
.
path
.
join
(
self
.
instance_root
,
'var'
,
'xml_report'
,
...
...
@@ -1744,7 +1906,7 @@ stderr_logfile_backups=1
# Whatever happens, don't stop processing other instances
except
Exception
:
self
.
logger
.
exception
(
'Cannot run usage script(s) for %r:'
%
computer_partition
.
get
Id
(
))
computer_partition
.
get
(
"compute_partition_id"
))
for
computer_partition_usage
in
computer_partition_usage_list
:
self
.
logger
.
info
(
'computer_partition_usage_list: %s - %s'
%
...
...
@@ -1770,7 +1932,7 @@ stderr_logfile_backups=1
if
self
.
validateXML
(
usage
,
computer_consumption_model
):
self
.
logger
.
info
(
'XML file generated by asXML is valid'
)
s
lap_computer_usage
.
reportUsage
(
usage
)
s
elf
.
computer
.
reportUsage
(
usage
)
filename_delete_list
.
append
(
filename
)
else
:
self
.
logger
.
info
(
'XML file is invalid %s'
%
file_path
)
...
...
@@ -1790,34 +1952,35 @@ stderr_logfile_backups=1
# We test the XML report before sending it
if
self
.
validateXML
(
computer_consumption
,
computer_consumption_model
):
self
.
logger
.
info
(
'XML file generated by asXML is valid'
)
s
lap_computer_usage
.
reportUsage
(
computer_consumption
)
s
elf
.
computer
.
reportUsage
(
computer_consumption
)
else
:
self
.
logger
.
info
(
'XML file generated by asXML is not valid !'
)
raise
ValueError
(
'XML file generated by asXML is not valid !'
)
except
Exception
:
issue
=
"Cannot report usage for %r: %s"
%
(
computer_partition
.
get
Id
(
),
computer_partition
.
get
(
"compute_partition_id"
),
traceback
.
format_exc
())
self
.
logger
.
info
(
issue
)
computer_partition
.
error
(
issue
,
logger
=
self
.
logger
)
self
.
sendPartitionError
(
computer_partition
,
issue
,
logger
=
self
.
logger
)
report_usage_issue_cp_list
.
append
(
computer_partition_id
)
for
computer_partition
in
computer_partition_list
:
if
computer_partition
.
get
State
(
)
==
COMPUTER_PARTITION_DESTROYED_STATE
:
if
computer_partition
.
get
(
"state"
)
==
COMPUTER_PARTITION_DESTROYED_STATE
:
destroyed
=
False
try
:
computer_partition_id
=
computer_partition
.
getId
()
computer_partition_id
=
computer_partition
.
get
(
"compute_partition_id"
)
software_url
=
computer_partition
.
get
(
"software_release_uri"
)
try
:
software_url
=
computer_partition
.
getSoftwareRelease
().
getURI
()
software_path
=
os
.
path
.
join
(
self
.
software_root
,
md5digest
(
software_url
))
except
(
NotFoundError
,
TypeError
):
software_url
=
None
except
TypeError
:
# Problem with instance: SR URI not set.
# Try to process it anyway, it may need to be deleted.
software_path
=
None
local_partition
=
Partition
(
software_path
=
software_path
,
instance_path
=
os
.
path
.
join
(
self
.
instance_root
,
computer_partition
.
get
Id
(
)),
computer_partition
.
get
(
"compute_partition_id"
)),
supervisord_partition_configuration_path
=
os
.
path
.
join
(
_getSupervisordConfigurationDirectory
(
self
.
instance_root
),
'%s.conf'
%
computer_partition_id
),
...
...
@@ -1837,9 +2000,16 @@ stderr_logfile_backups=1
local_partition
.
stop
()
local_partition
.
_updateCertificate
()
try
:
computer_partition
.
stopped
()
if
not
self
.
api_backward_compatibility
:
self
.
slap
.
jio_api_connector
.
put
({
"portal_type"
:
"Software Instance"
,
"reference"
:
computer_partition
.
get
(
"reference"
),
"reported_state"
:
"stopped"
})
else
:
computer_partition
[
"slap_partition"
].
stopped
()
except
(
SystemExit
,
KeyboardInterrupt
):
computer_partition
.
error
(
traceback
.
format_exc
(),
logger
=
self
.
logger
)
self
.
sendPartitionError
(
computer_partition
,
traceback
.
format_exc
(),
logger
=
self
.
logger
)
raise
except
Exception
:
pass
...
...
@@ -1847,9 +2017,9 @@ stderr_logfile_backups=1
for
manager
in
self
.
_manager_list
:
manager
.
report
(
local_partition
)
if
computer_partition
.
get
Id
(
)
in
report_usage_issue_cp_list
:
if
computer_partition
.
get
(
"compute_partition_id"
)
in
report_usage_issue_cp_list
:
self
.
logger
.
info
(
'Ignoring destruction of %r, as no report usage was sent'
%
computer_partition
.
get
Id
(
))
computer_partition
.
get
(
"compute_partition_id"
))
continue
if
self
.
_checkWaitProcessList
(
local_partition
,
state_list
=
[
'RUNNING'
,
'STARTING'
]):
...
...
@@ -1858,24 +2028,31 @@ stderr_logfile_backups=1
continue
destroyed
=
local_partition
.
destroy
()
except
(
SystemExit
,
KeyboardInterrupt
):
computer_partition
.
error
(
traceback
.
format_exc
(),
logger
=
self
.
logger
)
self
.
sendPartitionError
(
computer_partition
,
traceback
.
format_exc
(),
logger
=
self
.
logger
)
raise
except
Exception
:
clean_run
=
False
self
.
logger
.
exception
(
''
)
exc
=
traceback
.
format_exc
()
computer_partition
.
error
(
exc
,
logger
=
self
.
logger
)
self
.
sendPartitionError
(
computer_partition
,
exc
,
logger
=
self
.
logger
)
try
:
if
destroyed
:
computer_partition
.
destroyed
()
if
not
self
.
api_backward_compatibility
:
self
.
slap
.
jio_api_connector
.
put
({
"portal_type"
:
"Software Instance"
,
"reference"
:
computer_partition
.
get
(
"reference"
),
"reported_state"
:
"destroyed"
})
else
:
computer_partition
[
"slap_partition"
].
destroyed
()
except
NotFoundError
:
self
.
logger
.
debug
(
'Ignored slap error while trying to inform about '
'destroying not fully configured Computer Partition %r'
%
computer_partition
.
get
Id
(
))
computer_partition
.
get
(
"compute_partition_id"
))
except
ServerError
as
server_error
:
self
.
logger
.
debug
(
'Ignored server error while trying to inform about '
'destroying Computer Partition %r. Error is:
\
n
%r'
%
(
computer_partition
.
get
Id
(
),
server_error
.
args
[
0
]))
(
computer_partition
.
get
(
"compute_partition_id"
),
server_error
.
args
[
0
]))
self
.
logger
.
info
(
'Finished usage reports.'
)
...
...
slapos/manager/portredir.py
View file @
90a7f4a7
...
...
@@ -82,9 +82,8 @@ class Manager(object):
# Get partitions IPv6 address
computer_partition
=
partition
.
computer_partition
parameter_dict
=
computer_partition
.
getInstanceParameterDict
()
partition_ip_list
=
parameter_dict
[
'ip_list'
]
+
parameter_dict
.
get
(
partition_ip_list
=
computer_partition
[
'ip_list'
]
+
computer_partition
.
get
(
'full_ip_list'
,
[])
partition_ip_list
=
[
tup
[
1
]
for
tup
in
partition_ip_list
]
...
...
slapos/slap/slap.py
View file @
90a7f4a7
...
...
@@ -741,6 +741,36 @@ class SlapConnectionHelper(ConnectionHelper):
return
loads
(
xml
)
# https://stackoverflow.com/a/33571117
def
_byteify
(
data
,
ignore_dicts
=
False
):
if
isinstance
(
data
,
str
):
return
data
# if this is a list of values, return list of byteified values
if
isinstance
(
data
,
list
):
return
[
_byteify
(
item
,
ignore_dicts
=
True
)
for
item
in
data
]
# if this is a dictionary, return dictionary of byteified keys and values
# but only if we haven't already byteified it
if
isinstance
(
data
,
dict
)
and
not
ignore_dicts
:
return
{
_byteify
(
key
,
ignore_dicts
=
True
):
_byteify
(
value
,
ignore_dicts
=
True
)
for
key
,
value
in
data
.
items
()
# changed to .items() for python 2.7/3
}
# python 3 compatible duck-typing
# if this is a unicode string, return its string representation
if
str
(
type
(
data
))
==
"<type 'unicode'>"
:
return
data
.
encode
(
'utf-8'
)
# if it's anything else, return it in its original form
return
data
def
json_loads_byteified
(
json_text
):
return
_byteify
(
json
.
loads
(
json_text
,
object_hook
=
_byteify
),
ignore_dicts
=
True
)
class
JioAPIConnectionHelper
(
ConnectionHelper
):
def
apiCall
(
self
,
path
,
data
):
...
...
@@ -749,7 +779,7 @@ class JioAPIConnectionHelper(ConnectionHelper):
data
=
json
.
dumps
(
data
),
headers
=
{
'Content-type'
:
'application/json'
},
expect_json_error
=
True
)
return
req
.
json
(
)
return
json_loads_byteified
(
req
.
text
)
def
get
(
self
,
data
):
return
self
.
apiCall
(
path
=
"get/"
,
...
...
slapos/tests/test_slapgrid.py
View file @
90a7f4a7
...
...
@@ -193,7 +193,10 @@ class BasicMixin(object):
logger
=
logging
.
getLogger
(),
shared_part_list
=
self
.
shared_parts_root
,
force_stop
=
force_stop
,
certificate_repository_path
=
self
.
certificate_repository_path
)
certificate_repository_path
=
self
.
certificate_repository_path
,
slapgrid_jio_uri
=
self
.
master_url
+
"api/"
,
)
self
.
use_jio_api
=
True
self
.
grid
.
_manager_list
=
self
.
manager_list
# monkey patch buildout bootstrap
...
...
@@ -378,6 +381,29 @@ class MasterMixin(BasicMixin):
self
.
_unmock_sleep
()
BasicMixin
.
tearDown
(
self
)
class
SlapToolMasterMixin
(
MasterMixin
):
def
setSlapgrid
(
self
,
develop
=
False
,
force_stop
=
False
):
if
getattr
(
self
,
'master_url'
,
None
)
is
None
:
self
.
master_url
=
'http://127.0.0.1:80/'
self
.
computer_id
=
'computer'
self
.
supervisord_socket
=
os
.
path
.
join
(
self
.
_tempdir
,
'sv.sock'
)
self
.
supervisord_configuration_path
=
os
.
path
.
join
(
self
.
_tempdir
,
'supervisord'
)
self
.
usage_report_periodicity
=
1
self
.
buildout
=
None
self
.
grid
=
slapgrid
.
Slapgrid
(
self
.
software_root
,
self
.
instance_root
,
self
.
master_url
,
self
.
computer_id
,
self
.
buildout
,
develop
=
develop
,
logger
=
logging
.
getLogger
(),
shared_part_list
=
self
.
shared_parts_root
,
force_stop
=
force_stop
,
)
self
.
grid
.
_manager_list
=
self
.
manager_list
self
.
use_jio_api
=
False
# monkey patch buildout bootstrap
class
ComputerForTest
(
object
):
"""
...
...
@@ -393,6 +419,7 @@ class ComputerForTest(object):
Will set up instances, software and sequence
"""
self
.
sequence
=
[]
self
.
body_sequence
=
[]
self
.
instance_amount
=
instance_amount
self
.
software_amount
=
software_amount
self
.
software_root
=
software_root
...
...
@@ -421,6 +448,163 @@ class ComputerForTest(object):
qs
=
parse
.
parse_qs
(
url
.
query
)
else
:
qs
=
parse
.
parse_qs
(
req
.
body
)
# Catch API calls
if
url
.
path
.
startswith
(
'/api/'
):
content
=
json
.
loads
(
req
.
body
)
self
.
body_sequence
.
append
(
content
)
if
(
url
.
path
==
'/api/allDocs/'
):
if
content
[
"portal_type"
]
==
"Software Installation"
:
return
json
.
dumps
({
"result_list"
:
[{
"software_release_uri"
:
x
.
name
,
"portal_type"
:
"Software Installation"
,
"compute_node_id"
:
content
[
"compute_node_id"
],
"state"
:
x
.
requested_state
}
for
x
in
self
.
software_list
]
})
if
content
[
"portal_type"
]
==
"Software Instance"
:
if
"compute_node_id"
in
content
:
return
json
.
dumps
({
"result_list"
:
[{
"software_release_uri"
:
x
.
software
.
name
if
x
.
software
else
None
,
"reference"
:
x
.
name
,
"title"
:
x
.
name
,
"portal_type"
:
"Software Instance"
,
"compute_partition_id"
:
x
.
name
,
"state"
:
x
.
requested_state
}
for
x
in
self
.
instance_list
]
})
elif
"root_instance_title"
in
content
:
return
json
.
dumps
({
"result_list"
:
[{
"software_release_uri"
:
x
.
software
.
name
if
x
.
software
else
None
,
"reference"
:
x
.
name
,
"title"
:
x
.
name
,
"portal_type"
:
"Software Instance"
,
"compute_partition_id"
:
x
.
name
,
"state"
:
x
.
requested_state
}
for
x
in
self
.
instance_list
]
+
[
{
"software_release_uri"
:
"foo.cfg"
,
"reference"
:
"related_instance"
,
"title"
:
"related_instance"
,
"portal_type"
:
"Software Instance"
,
"compute_partition_id"
:
"related_instance"
,
"state"
:
"stopped"
}
]
})
elif
(
url
.
path
==
'/api/put/'
):
if
content
[
"portal_type"
]
==
"Software Installation"
:
software
=
self
.
software_list
[
0
]
software
.
sequence
.
append
((
url
.
path
,
content
))
if
"error_status"
in
content
:
software
.
error_log
=
content
[
'error_status'
]
software
.
error
=
True
return
json
.
dumps
({
"id"
:
content
[
"software_release_uri"
]})
elif
content
[
"portal_type"
]
==
"Software Instance"
:
reference
=
content
[
"reference"
]
requested_instance
=
None
for
instance
in
self
.
instance_list
:
if
instance
.
name
==
reference
:
requested_instance
=
instance
break
if
requested_instance
:
requested_instance
.
sequence
.
append
((
url
.
path
,
content
))
if
"reported_state"
in
content
:
if
content
[
"reported_state"
]
==
"error"
:
instance
.
error
=
True
instance
.
error_log
=
content
[
"status_message"
]
else
:
requested_instance
.
state
=
content
[
"reported_state"
]
return
json
.
dumps
({
"reference"
:
requested_instance
.
name
,
"portal_type"
:
"Software Instance"
,
"success"
:
"Done"
},
indent
=
2
)
if
"requested_instance_list"
in
content
:
return
json
.
dumps
({
"reference"
:
requested_instance
.
name
,
"portal_type"
:
"Software Instance"
,
"success"
:
"Done"
},
indent
=
2
)
else
:
return
json
.
dumps
({
"status"
:
"404"
,
"message"
:
"No document found with parameters: %s"
%
reference
,
"name"
:
"NotFound"
,
})
elif
(
url
.
path
==
'/api/get/'
):
if
content
[
"portal_type"
]
==
"Software Instance"
:
reference
=
content
[
"reference"
]
# Treat the case of firewall
if
reference
==
"related_instance"
:
return
json
.
dumps
({
"title"
:
"related_instance"
,
"reference"
:
"related_instance"
,
"software_release_uri"
:
"foo.cfg"
,
"software_type"
:
None
,
"state"
:
"stopped"
,
"connection_parameters"
:
{
},
"parameters"
:
{},
"shared"
:
False
,
"root_instance_title"
:
"0"
,
"ip_list"
:
self
.
ip_address_list
,
"X509"
:
{
"certificate"
:
""
,
"key"
:
""
},
"sla_parameters"
:
{},
"compute_node_id"
:
None
,
"compute_partition_id"
:
"requested_instance"
,
"processing_timestamp"
:
0
,
"access_status_message"
:
""
,
"portal_type"
:
"Software Instance"
})
requested_instance
=
None
for
instance
in
self
.
instance_list
:
if
instance
.
name
==
reference
:
requested_instance
=
instance
break
if
requested_instance
:
requested_instance
.
sequence
.
append
((
url
.
path
,
content
))
return
json
.
dumps
({
"title"
:
requested_instance
.
name
,
"reference"
:
requested_instance
.
name
,
"software_release_uri"
:
requested_instance
.
software
.
name
,
"software_type"
:
None
,
"state"
:
requested_instance
.
requested_state
,
"connection_parameters"
:
{
},
"parameters"
:
{},
"shared"
:
False
,
"root_instance_title"
:
requested_instance
.
name
,
"ip_list"
:
requested_instance
.
ip_list
,
"full_ip_list"
:
requested_instance
.
full_ip_list
,
"X509"
:
{
"certificate"
:
requested_instance
.
certificate
,
"key"
:
requested_instance
.
key
},
"sla_parameters"
:
requested_instance
.
filter_dict
,
"compute_node_id"
:
None
,
"compute_partition_id"
:
requested_instance
.
name
,
"processing_timestamp"
:
requested_instance
.
timestamp
,
"access_status_message"
:
requested_instance
.
error_log
,
"portal_type"
:
"Software Instance"
})
else
:
return
json
.
dumps
({
"status"
:
"404"
,
"message"
:
"No document found with parameters: %s"
%
reference
,
"name"
:
"NotFound"
,
})
raise
ValueError
(
"Unexcepted call to API. URL:%s Content:%s"
%
(
url
.
path
,
req
.
body
))
if
(
url
.
path
==
'/getFullComputerInformation'
and
'computer_id'
in
qs
):
slap_computer
=
self
.
getComputer
(
qs
[
'computer_id'
][
0
])
...
...
@@ -557,6 +741,10 @@ class InstanceForTest(object):
self
.
ip_list
=
[(
'interface0'
,
'10.0.8.2'
)]
self
.
full_ip_list
=
[(
'route_interface0'
,
'10.10.2.3'
,
'10.10.0.1'
,
'255.0.0.0'
,
'10.0.0.0'
)]
self
.
certificate
=
str
(
random
.
random
())
self
.
key
=
str
(
random
.
random
())
self
.
filter_dict
=
{}
def
getInstance
(
self
,
computer_id
,
):
"""
...
...
@@ -565,8 +753,7 @@ class InstanceForTest(object):
partition
=
slapos
.
slap
.
ComputerPartition
(
computer_id
,
self
.
name
)
partition
.
_software_release_document
=
self
.
getSoftwareRelease
()
partition
.
_requested_state
=
self
.
requested_state
if
getattr
(
self
,
'filter_dict'
,
None
):
partition
.
_filter_dict
=
self
.
filter_dict
partition
.
_filter_dict
=
self
.
filter_dict
partition
.
_parameter_dict
=
{
'ip_list'
:
self
.
ip_list
,
'full_ip_list'
:
self
.
full_ip_list
}
...
...
@@ -624,12 +811,10 @@ class InstanceForTest(object):
os
.
mkdir
(
certificate_repository_path
)
self
.
cert_file
=
os
.
path
.
join
(
certificate_repository_path
,
"%s.crt"
%
self
.
name
)
self
.
certificate
=
str
(
random
.
random
())
with
open
(
self
.
cert_file
,
'w'
)
as
f
:
f
.
write
(
self
.
certificate
)
self
.
key_file
=
os
.
path
.
join
(
certificate_repository_path
,
'%s.key'
%
self
.
name
)
self
.
key
=
str
(
random
.
random
())
with
open
(
self
.
key_file
,
'w'
)
as
f
:
f
.
write
(
self
.
key
)
...
...
@@ -735,11 +920,9 @@ class TestSlapgridCPWithMaster(MasterMixin, unittest.TestCase):
'software_release'
,
'worked'
,
'.slapos-retention-lock-delay'
])
six
.
assertCountEqual
(
self
,
os
.
listdir
(
self
.
software_root
),
[
instance
.
software
.
software_hash
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/stoppedComputerPartition'
])
self
.
assertEqual
(
open
(
os
.
path
.
join
(
self
.
certificate_repository_path
,
'0.crt'
)).
read
(),
'SLAPOS_cert'
)
self
.
assertEqual
(
open
(
os
.
path
.
join
(
self
.
certificate_repository_path
,
'0.key'
)).
read
(),
'SLAPOS_key'
)
[
'/api/allDocs/'
,
'/api/get/'
,
'/api/put/'
])
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
self
.
assertEqual
(
instance
.
state
,
'stopped'
)
def
test_one_partition_instance_cfg
(
self
):
"""
...
...
@@ -756,9 +939,9 @@ class TestSlapgridCPWithMaster(MasterMixin, unittest.TestCase):
'software_release'
,
'worked'
,
'.slapos-retention-lock-delay'
])
six
.
assertCountEqual
(
self
,
os
.
listdir
(
self
.
software_root
),
[
instance
.
software
.
software_hash
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/
getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/stoppedComputerPartition'
]
)
[
'/
api/allDocs/'
,
'/api/get/'
,
'/api/put/'
])
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
self
.
assertEqual
(
instance
.
state
,
'stopped'
)
def
test_one_free_partition
(
self
):
"""
...
...
@@ -791,9 +974,8 @@ class TestSlapgridCPWithMaster(MasterMixin, unittest.TestCase):
self
.
assertLogContent
(
wrapper_log
,
'Working'
)
six
.
assertCountEqual
(
self
,
os
.
listdir
(
self
.
software_root
),
[
partition
.
software
.
software_hash
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/startedComputerPartition'
])
[
'/api/allDocs/'
,
'/api/get/'
,
'/api/put/'
])
self
.
assertEqual
(
partition
.
sequence
[
1
][
1
][
"reported_state"
],
'started'
)
self
.
assertEqual
(
partition
.
state
,
'started'
)
def
test_one_partition_started_fail
(
self
):
...
...
@@ -811,9 +993,8 @@ class TestSlapgridCPWithMaster(MasterMixin, unittest.TestCase):
self
.
assertLogContent
(
wrapper_log
,
'Working'
)
six
.
assertCountEqual
(
self
,
os
.
listdir
(
self
.
software_root
),
[
partition
.
software
.
software_hash
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/startedComputerPartition'
])
[
'/api/allDocs/'
,
'/api/get/'
,
'/api/put/'
])
self
.
assertEqual
(
partition
.
sequence
[
1
][
1
][
"reported_state"
],
'started'
)
self
.
assertEqual
(
partition
.
state
,
'started'
)
instance
=
computer
.
instance_list
[
0
]
...
...
@@ -827,14 +1008,11 @@ exit 1
'etc'
,
'software_release'
,
'worked'
,
'.slapos-retention-lock-delay'
,
'.slapgrid-0-error.log'
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/startedComputerPartition'
,
'/getHateoasUrl'
,
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/softwareInstanceError'
])
[
'/api/allDocs/'
,
'/api/get/'
,
'/api/put/'
,
'/getHateoasUrl'
,
'/api/allDocs/'
,
'/api/get/'
,
'/api/put/'
])
self
.
assertEqual
(
instance
.
sequence
[
3
][
1
][
"reported_state"
],
'error'
)
self
.
assertEqual
(
instance
.
state
,
'started'
)
self
.
assertTrue
(
instance
.
error_log
.
startswith
(
"Failed to run buildout profile in direct"
))
def
test_one_partition_started_stopped
(
self
):
computer
=
self
.
getTestComputerClass
()(
self
.
software_root
,
self
.
instance_root
)
...
...
@@ -871,9 +1049,8 @@ chmod 755 etc/run/wrapper
self
.
assertLogContent
(
wrapper_log
,
'Working'
)
six
.
assertCountEqual
(
self
,
os
.
listdir
(
self
.
software_root
),
[
instance
.
software
.
software_hash
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/startedComputerPartition'
])
[
'/api/allDocs/'
,
'/api/get/'
,
'/api/put/'
])
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'started'
)
self
.
assertEqual
(
instance
.
state
,
'started'
)
computer
.
sequence
=
[]
...
...
@@ -886,9 +1063,8 @@ chmod 755 etc/run/wrapper
self
.
assertLogContent
(
wrapper_log
,
'Signal handler called with signal 15'
)
self
.
assertEqual
(
computer
.
sequence
,
[
'/getHateoasUrl'
,
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/stoppedComputerPartition'
])
'/api/allDocs/'
,
'/api/get/'
,
'/api/put/'
])
self
.
assertEqual
(
instance
.
sequence
[
3
][
1
][
"reported_state"
],
'stopped'
)
self
.
assertEqual
(
instance
.
state
,
'stopped'
)
def
test_one_broken_partition_stopped
(
self
):
...
...
@@ -932,9 +1108,10 @@ chmod 755 etc/run/wrapper
six
.
assertCountEqual
(
self
,
os
.
listdir
(
self
.
software_root
),
[
instance
.
software
.
software_hash
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/startedComputerPartition'
])
[
'/api/allDocs/'
,
'/api/get/'
,
'/api/put/'
])
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'started'
)
self
.
assertEqual
(
instance
.
state
,
'started'
)
computer
.
sequence
=
[]
...
...
@@ -951,10 +1128,12 @@ exit 1
self
.
assertLogContent
(
wrapper_log
,
'Signal handler called with signal 15'
)
self
.
assertEqual
(
computer
.
sequence
,
[
'/getHateoasUrl'
,
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/softwareInstanceError'
])
'/api/allDocs/'
,
'/api/get/'
,
'/api/put/'
])
self
.
assertEqual
(
instance
.
sequence
[
3
][
1
][
"reported_state"
],
'error'
)
self
.
assertEqual
(
instance
.
state
,
'started'
)
self
.
assertTrue
(
instance
.
error_log
.
startswith
(
"Failed to run buildout profile in direct"
))
def
test_one_partition_stopped_started
(
self
):
computer
=
self
.
getTestComputerClass
()(
self
.
software_root
,
self
.
instance_root
)
...
...
@@ -971,9 +1150,10 @@ exit 1
six
.
assertCountEqual
(
self
,
os
.
listdir
(
self
.
software_root
),
[
instance
.
software
.
software_hash
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/stoppedComputerPartition'
])
[
'/api/allDocs/'
,
'/api/get/'
,
'/api/put/'
])
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
self
.
assertEqual
(
'stopped'
,
instance
.
state
)
instance
.
requested_state
=
'started'
...
...
@@ -990,9 +1170,10 @@ exit 1
self
.
assertLogContent
(
wrapper_log
,
'Working'
)
self
.
assertEqual
(
computer
.
sequence
,
[
'/getHateoasUrl'
,
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/startedComputerPartition'
])
'/api/allDocs/'
,
'/api/get/'
,
'/api/put/'
])
self
.
assertEqual
(
instance
.
sequence
[
3
][
1
][
"reported_state"
],
'started'
)
self
.
assertEqual
(
'started'
,
instance
.
state
)
def
test_one_partition_destroyed
(
self
):
...
...
@@ -1016,9 +1197,10 @@ exit 1
six
.
assertCountEqual
(
self
,
os
.
listdir
(
partition
),
[
'.slapgrid'
,
dummy_file_name
])
six
.
assertCountEqual
(
self
,
os
.
listdir
(
self
.
software_root
),
[
instance
.
software
.
software_hash
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/stoppedComputerPartition'
])
[
'/api/allDocs/'
,
'/api/get/'
,
'/api/put/'
])
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
self
.
assertEqual
(
'stopped'
,
instance
.
state
)
...
...
@@ -1408,8 +1590,8 @@ class TestSlapgridCPPartitionProcessing(MasterMixin, unittest.TestCase):
self
.
assertEqual
(
self
.
grid
.
processComputerPartitionList
(),
slapgrid
.
SLAPGRID_SUCCESS
)
with
open
(
timestamp_path
)
as
f
:
self
.
assertIn
(
timestamp
,
f
.
read
())
self
.
assertEqual
(
instance
.
sequence
,
[
'/stoppedComputerPartition'
]
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
def
test_partition_timestamp_develop
(
self
):
computer
=
self
.
getTestComputerClass
()(
self
.
software_root
,
self
.
instance_root
)
...
...
@@ -1430,9 +1612,10 @@ class TestSlapgridCPPartitionProcessing(MasterMixin, unittest.TestCase):
slapgrid
.
SLAPGRID_SUCCESS
)
self
.
assertEqual
(
self
.
launchSlapgrid
(),
slapgrid
.
SLAPGRID_SUCCESS
)
self
.
assertEqual
(
instance
.
sequence
,
[
'/stoppedComputerPartition'
,
'/stoppedComputerPartition'
])
self
.
assertEqual
(
instance
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
self
.
assertEqual
(
instance
.
sequence
[
3
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance
.
sequence
[
3
][
1
][
"reported_state"
],
'stopped'
)
def
test_partition_old_timestamp
(
self
):
computer
=
self
.
getTestComputerClass
()(
self
.
software_root
,
self
.
instance_root
)
...
...
@@ -1449,8 +1632,8 @@ class TestSlapgridCPPartitionProcessing(MasterMixin, unittest.TestCase):
six
.
assertCountEqual
(
self
,
os
.
listdir
(
self
.
software_root
),
[
instance
.
software
.
software_hash
])
instance
.
timestamp
=
str
(
int
(
timestamp
)
-
1
)
self
.
assertEqual
(
self
.
launchSlapgrid
(),
slapgrid
.
SLAPGRID_SUCCESS
)
self
.
assertEqual
(
instance
.
sequence
,
[
'/stoppedComputerPartition'
]
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
def
test_partition_timestamp_new_timestamp
(
self
):
computer
=
self
.
getTestComputerClass
()(
self
.
software_root
,
self
.
instance_root
)
...
...
@@ -1468,17 +1651,10 @@ class TestSlapgridCPPartitionProcessing(MasterMixin, unittest.TestCase):
instance
.
timestamp
=
str
(
int
(
timestamp
)
+
1
)
self
.
assertEqual
(
self
.
launchSlapgrid
(),
slapgrid
.
SLAPGRID_SUCCESS
)
self
.
assertEqual
(
self
.
launchSlapgrid
(),
slapgrid
.
SLAPGRID_SUCCESS
)
self
.
assertEqual
(
computer
.
sequence
,
[
'/getHateoasUrl'
,
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/stoppedComputerPartition'
,
'/getHateoasUrl'
,
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/stoppedComputerPartition'
,
'/getHateoasUrl'
,
'/getFullComputerInformation'
])
self
.
assertEqual
(
[
x
[
0
]
for
x
in
instance
.
sequence
],
[
'/api/get/'
,
'/api/put/'
,
'/api/get/'
,
'/api/put/'
,
'/api/get/'
]
)
def
test_partition_timestamp_no_timestamp
(
self
):
computer
=
self
.
getTestComputerClass
()(
self
.
software_root
,
self
.
instance_root
)
...
...
@@ -1496,15 +1672,10 @@ class TestSlapgridCPPartitionProcessing(MasterMixin, unittest.TestCase):
[
instance
.
software
.
software_hash
])
instance
.
timestamp
=
None
self
.
launchSlapgrid
()
self
.
assertEqual
(
computer
.
sequence
,
[
'/getHateoasUrl'
,
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/stoppedComputerPartition'
,
'/getHateoasUrl'
,
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/stoppedComputerPartition'
])
self
.
assertEqual
(
[
x
[
0
]
for
x
in
instance
.
sequence
],
[
'/api/get/'
,
'/api/put/'
,
'/api/get/'
,
'/api/put/'
]
)
def
test_partition_periodicity_remove_timestamp
(
self
):
"""
...
...
@@ -1569,17 +1740,17 @@ class TestSlapgridCPPartitionProcessing(MasterMixin, unittest.TestCase):
os
.
path
.
join
(
instance0
.
partition_path
,
'.timestamp'
))
time
.
sleep
(
wanted_periodicity
+
1
)
for
instance
in
computer
.
instance_list
[
1
:]:
self
.
assertEqual
(
instance
.
sequence
,
[
'/stoppedComputerPartition'
]
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
time
.
sleep
(
1
)
self
.
launchSlapgrid
()
self
.
assertEqual
(
instance0
.
sequence
,
[
'/startedComputerPartition'
,
'/startedComputerPartition'
,
]
)
self
.
assertEqual
(
instance0
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance0
.
sequence
[
1
][
1
][
"reported_state"
],
'started'
)
self
.
assertEqual
(
instance0
.
sequence
[
3
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance0
.
sequence
[
3
][
1
][
"reported_state"
],
'started'
)
for
instance
in
computer
.
instance_list
[
1
:]:
self
.
assertEqual
(
instance
.
sequence
,
[
'/stoppedComputerPartition'
]
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
self
.
assertGreater
(
os
.
path
.
getmtime
(
os
.
path
.
join
(
instance0
.
partition_path
,
'.timestamp'
)),
last_runtime
)
...
...
@@ -1609,16 +1780,17 @@ class TestSlapgridCPPartitionProcessing(MasterMixin, unittest.TestCase):
os
.
path
.
join
(
instance0
.
partition_path
,
'.timestamp'
))
time
.
sleep
(
wanted_periodicity
+
1
)
for
instance
in
computer
.
instance_list
[
1
:]:
self
.
assertEqual
(
instance
.
sequence
,
[
'/stoppedComputerPartition'
]
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
time
.
sleep
(
1
)
self
.
launchSlapgrid
()
self
.
assertEqual
(
instance0
.
sequence
,
[
'/stoppedComputerPartition'
,
'/stoppedComputerPartition'
])
self
.
assertEqual
(
instance0
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance0
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
self
.
assertEqual
(
instance0
.
sequence
[
3
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance0
.
sequence
[
3
][
1
][
"reported_state"
],
'stopped'
)
for
instance
in
computer
.
instance_list
[
1
:]:
self
.
assertEqual
(
instance
.
sequence
,
[
'/stoppedComputerPartition'
]
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
self
.
assertNotEqual
(
os
.
path
.
getmtime
(
os
.
path
.
join
(
instance0
.
partition_path
,
'.timestamp'
)),
last_runtime
)
...
...
@@ -1649,17 +1821,19 @@ class TestSlapgridCPPartitionProcessing(MasterMixin, unittest.TestCase):
os
.
path
.
join
(
instance0
.
partition_path
,
'.timestamp'
))
time
.
sleep
(
wanted_periodicity
+
1
)
for
instance
in
computer
.
instance_list
[
1
:]:
self
.
assertEqual
(
instance
.
sequence
,
[
'/stoppedComputerPartition'
]
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
time
.
sleep
(
1
)
instance0
.
requested_state
=
'destroyed'
self
.
launchSlapgrid
()
self
.
assertEqual
(
instance0
.
sequence
,
[
'/stoppedComputerPartition'
,
'/stoppedComputerPartition'
])
self
.
assertEqual
(
instance0
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance0
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
self
.
assertEqual
(
instance0
.
sequence
[
3
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance0
.
sequence
[
3
][
1
][
"reported_state"
],
'stopped'
)
for
instance
in
computer
.
instance_list
[
1
:]:
self
.
assertEqual
(
instance
.
sequence
,
[
'/stoppedComputerPartition'
]
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
self
.
assertNotEqual
(
os
.
path
.
getmtime
(
os
.
path
.
join
(
instance0
.
partition_path
,
'.timestamp'
)),
last_runtime
)
...
...
@@ -1723,10 +1897,15 @@ class TestSlapgridCPPartitionProcessing(MasterMixin, unittest.TestCase):
instance0
.
software
.
setBuildout
(
"""#!/bin/sh
exit 42"""
)
self
.
launchSlapgrid
()
self
.
assertEqual
(
instance0
.
sequence
,
[
'/softwareInstanceError'
])
self
.
assertEqual
(
instance1
.
sequence
,
[
'/stoppedComputerPartition'
])
self
.
assertTrue
(
instance0
.
error_log
.
startswith
(
"Failed to run buildout profile in direct"
))
self
.
assertEqual
(
instance1
.
sequence
[
1
],
(
'/api/put/'
,
{
'portal_type'
:
'Software Instance'
,
'reference'
:
'1'
,
'reported_state'
:
'stopped'
}
)
)
def
test_one_partition_lacking_software_path_does_not_disturb_others
(
self
):
"""
...
...
@@ -1740,10 +1919,15 @@ exit 42""")
instance1
.
software
=
computer
.
software_list
[
1
]
shutil
.
rmtree
(
instance0
.
software
.
srdir
)
self
.
launchSlapgrid
()
self
.
assertEqual
(
instance0
.
sequence
,
[
'/softwareInstanceError'
])
self
.
assertEqual
(
instance1
.
sequence
,
[
'/stoppedComputerPartition'
])
self
.
assertEqual
(
instance0
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance0
.
sequence
[
1
][
1
][
"reported_state"
],
'error'
)
self
.
assertIn
(
"Software Release http://sr0/ is not present on system"
,
instance0
.
sequence
[
1
][
1
][
"status_message"
]
)
self
.
assertIn
(
"Cannot deploy instance."
,
instance0
.
sequence
[
1
][
1
][
"status_message"
])
self
.
assertEqual
(
instance1
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance1
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
def
test_one_partition_lacking_software_bin_path_does_not_disturb_others
(
self
):
"""
...
...
@@ -1757,10 +1941,12 @@ exit 42""")
instance1
.
software
=
computer
.
software_list
[
1
]
shutil
.
rmtree
(
instance0
.
software
.
srbindir
)
self
.
launchSlapgrid
()
self
.
assertEqual
(
instance0
.
sequence
,
[
'/softwareInstanceError'
])
self
.
assertEqual
(
instance1
.
sequence
,
[
'/stoppedComputerPartition'
])
self
.
assertEqual
(
instance0
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance0
.
sequence
[
1
][
1
][
"reported_state"
],
'error'
)
self
.
assertIn
(
"No such file or directory"
,
instance0
.
sequence
[
1
][
1
][
"status_message"
])
self
.
assertIn
(
"sbin/buildout"
,
instance0
.
sequence
[
1
][
1
][
"status_message"
])
self
.
assertEqual
(
instance1
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance1
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
def
test_one_partition_lacking_path_does_not_disturb_others
(
self
):
"""
...
...
@@ -1774,10 +1960,12 @@ exit 42""")
instance1
.
software
=
computer
.
software_list
[
1
]
shutil
.
rmtree
(
instance0
.
partition_path
)
self
.
launchSlapgrid
()
self
.
assertEqual
(
instance0
.
sequence
,
[
'/softwareInstanceError'
])
self
.
assertEqual
(
instance1
.
sequence
,
[
'/stoppedComputerPartition'
])
self
.
assertEqual
(
instance0
.
sequence
[
0
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance0
.
sequence
[
0
][
1
][
"reported_state"
],
'error'
)
self
.
assertIn
(
"Partition directory"
,
instance0
.
sequence
[
0
][
1
][
"status_message"
])
self
.
assertIn
(
"does not exist"
,
instance0
.
sequence
[
0
][
1
][
"status_message"
])
self
.
assertEqual
(
instance1
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance1
.
sequence
[
1
][
1
][
"reported_state"
],
'stopped'
)
def
test_one_partition_buildout_fail_is_correctly_logged
(
self
):
"""
...
...
@@ -1793,7 +1981,8 @@ exit 42""")
instance
.
software
.
setBuildout
(
"""#!/bin/sh
echo %s; echo %s; exit 42"""
%
(
line1
,
line2
))
self
.
launchSlapgrid
()
self
.
assertEqual
(
instance
.
sequence
,
[
'/softwareInstanceError'
])
self
.
assertEqual
(
instance
.
sequence
[
1
][
0
],
'/api/put/'
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
"error"
)
# We don't care of actual formatting, we just want to have full log
self
.
assertIn
(
line1
,
instance
.
error_log
)
self
.
assertIn
(
line2
,
instance
.
error_log
)
...
...
@@ -1876,7 +2065,8 @@ echo %s; echo %s; exit 42""" % (line1, line2))
[
'etc'
,
'.slapgrid'
,
'buildout.cfg'
,
'software_release'
,
'worked'
,
'.slapos-retention-lock-delay'
]
)
self
.
assertFalse
(
os
.
path
.
exists
(
promise_ran
))
self
.
assertFalse
(
instance
.
sequence
)
self
.
assertEqual
(
len
(
instance
.
sequence
),
1
)
self
.
assertEqual
(
instance
.
sequence
[
0
][
0
],
"/api/get/"
)
class
TestSlapgridUsageReport
(
MasterMixin
,
unittest
.
TestCase
):
...
...
@@ -1902,14 +2092,18 @@ class TestSlapgridUsageReport(MasterMixin, unittest.TestCase):
self
.
assertLogContent
(
wrapper_log
,
'Working'
)
six
.
assertCountEqual
(
self
,
os
.
listdir
(
self
.
software_root
),
[
instance
.
software
.
software_hash
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/startedComputerPartition'
])
[
'/api/allDocs/'
,
'/api/get/'
,
'/api/put/'
])
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'started'
)
self
.
assertEqual
(
instance
.
state
,
'started'
)
# Then destroy the instance
computer
.
sequence
=
[]
instance
.
sequence
=
[]
instance
.
requested_state
=
'destroyed'
# Reset Cache
self
.
grid
.
computer_partition_list
=
None
self
.
assertEqual
(
self
.
grid
.
agregateAndSendUsage
(),
slapgrid
.
SLAPGRID_SUCCESS
)
# Assert partition directory is empty
self
.
assertInstanceDirectoryListEqual
([
'0'
])
...
...
@@ -1921,10 +2115,11 @@ class TestSlapgridUsageReport(MasterMixin, unittest.TestCase):
self
.
assertIsNotCreated
(
wrapper_log
)
self
.
assertEqual
(
computer
.
sequence
,
[
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/stoppedComputerPartition'
,
'/destroyedComputerPartition'
])
[
'/api/allDocs/'
,
'/api/put/'
,
'/api/put/'
])
self
.
assertEqual
(
instance
.
sequence
[
0
][
1
][
"reported_state"
],
'stopped'
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'destroyed'
)
self
.
assertEqual
(
instance
.
state
,
'destroyed'
)
def
test_partition_list_is_complete_if_empty_destroyed_partition
(
self
):
...
...
@@ -1942,6 +2137,7 @@ class TestSlapgridUsageReport(MasterMixin, unittest.TestCase):
computer
.
sequence
=
[]
instance
.
requested_state
=
'destroyed'
self
.
grid
.
computer_partition_list
=
None
self
.
assertEqual
(
self
.
grid
.
agregateAndSendUsage
(),
slapgrid
.
SLAPGRID_SUCCESS
)
# Assert partition directory is empty
self
.
assertInstanceDirectoryListEqual
([
'0'
])
...
...
@@ -1952,12 +2148,13 @@ class TestSlapgridUsageReport(MasterMixin, unittest.TestCase):
wrapper_log
=
os
.
path
.
join
(
instance
.
partition_path
,
'.0_wrapper.log'
)
self
.
assertIsNotCreated
(
wrapper_log
)
self
.
assertEqual
(
computer
.
sequence
,
[
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/stoppedComputerPartition'
,
'/destroyedComputerPartition'
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/api/allDocs/'
,
'/api/put/'
,
'/api/put/'
])
self
.
assertEqual
(
instance
.
sequence
[
0
][
1
][
"reported_state"
],
'stopped'
)
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'destroyed'
)
self
.
assertEqual
(
instance
.
state
,
'destroyed'
)
def
test_slapgrid_not_destroy_bad_instance
(
self
):
"""
...
...
@@ -1977,33 +2174,32 @@ class TestSlapgridUsageReport(MasterMixin, unittest.TestCase):
self
.
assertLogContent
(
wrapper_log
,
'Working'
)
six
.
assertCountEqual
(
self
,
os
.
listdir
(
self
.
software_root
),
[
instance
.
software
.
software_hash
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/startedComputerPartition'
])
self
.
assertEqual
(
'started'
,
instance
.
state
)
[
'/api/allDocs/'
,
'/api/get/'
,
'/api/put/'
])
self
.
assertEqual
(
instance
.
sequence
[
1
][
1
][
"reported_state"
],
'started'
)
self
.
assertEqual
(
instance
.
state
,
'started'
)
# Then run usage report and see if it is still working
computer
.
sequence
=
[]
self
.
grid
.
computer_partition_list
=
None
self
.
assertEqual
(
self
.
grid
.
agregateAndSendUsage
(),
slapgrid
.
SLAPGRID_SUCCESS
)
# registerComputerPartition will create one more file:
from
slapos.slap.slap
import
COMPUTER_PARTITION_REQUEST_LIST_TEMPLATE_FILENAME
request_list_file
=
COMPUTER_PARTITION_REQUEST_LIST_TEMPLATE_FILENAME
%
instance
.
name
self
.
assertInstanceDirectoryListEqual
([
'0'
])
six
.
assertCountEqual
(
self
,
os
.
listdir
(
instance
.
partition_path
),
[
'.slapgrid'
,
'.0_wrapper.log'
,
'buildout.cfg'
,
'etc'
,
'software_release'
,
'worked'
,
'.slapos-retention-lock-delay'
,
request_list_file
])
'.slapos-retention-lock-delay'
])
wrapper_log
=
os
.
path
.
join
(
instance
.
partition_path
,
'.0_wrapper.log'
)
self
.
assertLogContent
(
wrapper_log
,
'Working'
)
self
.
assertInstanceDirectoryListEqual
([
'0'
])
six
.
assertCountEqual
(
self
,
os
.
listdir
(
instance
.
partition_path
),
[
'.slapgrid'
,
'.0_wrapper.log'
,
'buildout.cfg'
,
'etc'
,
'software_release'
,
'worked'
,
'.slapos-retention-lock-delay'
,
request_list_file
])
'.slapos-retention-lock-delay'
])
wrapper_log
=
os
.
path
.
join
(
instance
.
partition_path
,
'.0_wrapper.log'
)
self
.
assertLogContent
(
wrapper_log
,
'Working'
)
self
.
assertEqual
(
computer
.
sequence
,
[
'/
getFullComputerInformation
'
])
[
'/
api/allDocs/
'
])
self
.
assertEqual
(
'started'
,
instance
.
state
)
def
test_slapgrid_instance_ignore_free_instance
(
self
):
...
...
@@ -2023,7 +2219,7 @@ class TestSlapgridUsageReport(MasterMixin, unittest.TestCase):
self
.
assertInstanceDirectoryListEqual
([
'0'
])
six
.
assertCountEqual
(
self
,
os
.
listdir
(
instance
.
partition_path
),
[])
six
.
assertCountEqual
(
self
,
os
.
listdir
(
self
.
software_root
),
[
instance
.
software
.
software_hash
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/
getFullComputerInformation
'
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/
api/allDocs/
'
])
def
test_slapgrid_report_ignore_free_instance
(
self
):
"""
...
...
@@ -2042,10 +2238,10 @@ class TestSlapgridUsageReport(MasterMixin, unittest.TestCase):
self
.
assertInstanceDirectoryListEqual
([
'0'
])
six
.
assertCountEqual
(
self
,
os
.
listdir
(
instance
.
partition_path
),
[])
six
.
assertCountEqual
(
self
,
os
.
listdir
(
self
.
software_root
),
[
instance
.
software
.
software_hash
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/
getFullComputerInformation
'
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/
api/allDocs/
'
])
class
TestSlapgridSoftwareRelease
(
MasterMixin
,
unittest
.
TestCase
):
class
TestSlapgridSoftwareRelease
SlapTool
(
SlapTool
MasterMixin
,
unittest
.
TestCase
):
fake_waiting_time
=
0.05
def
test_one_software_buildout_fail_is_correctly_logged
(
self
):
...
...
@@ -2114,6 +2310,95 @@ chmod a-rxw directory
self
.
launchSlapgridSoftware
()
self
.
assertEqual
(
os
.
listdir
(
self
.
software_root
),
[])
class
TestSlapgridSoftwareRelease
(
MasterMixin
,
unittest
.
TestCase
):
fake_waiting_time
=
0.05
def
test_one_software_buildout_fail_is_correctly_logged
(
self
):
"""
1. We set up a software using a corrupted buildout
2. It will fail, make sure that whole log is sent to master
"""
computer
=
ComputerForTest
(
self
.
software_root
,
self
.
instance_root
,
1
,
1
)
with
httmock
.
HTTMock
(
computer
.
request_handler
):
software
=
computer
.
software_list
[
0
]
line1
=
"Nerdy kitten: Can I haz a process crash?"
line2
=
"Cedric: Sure, here it is."
software
.
setBuildout
(
"""#!/bin/sh
echo %s; echo %s; exit 42"""
%
(
line1
,
line2
))
self
.
launchSlapgridSoftware
()
self
.
assertEqual
(
software
.
sequence
,
[
(
'/api/put/'
,
{
'compute_node_id'
:
self
.
computer_id
,
'portal_type'
:
'Software Installation'
,
'reported_state'
:
'building'
,
'software_release_uri'
:
software
.
name
,
}
),
(
'/api/put/'
,
{
'compute_node_id'
:
self
.
computer_id
,
'portal_type'
:
'Software Installation'
,
'error_status'
:
software
.
error_log
,
'software_release_uri'
:
software
.
name
,
}
)
]
)
# We don't care of actual formatting, we just want to have full log
self
.
assertIn
(
line1
,
software
.
error_log
)
self
.
assertIn
(
line2
,
software
.
error_log
)
self
.
assertIn
(
'Failed to run buildout'
,
software
.
error_log
)
def
test_software_install_generate_buildout_cfg_with_shared_part_list
(
self
):
computer
=
ComputerForTest
(
self
.
software_root
,
self
.
instance_root
,
1
,
1
)
with
httmock
.
HTTMock
(
computer
.
request_handler
):
software
=
computer
.
software_list
[
0
]
# examine the genrated buildout
software
.
setBuildout
(
"""#!/bin/sh
cat buildout.cfg; exit 1"""
)
self
.
launchSlapgridSoftware
()
self
.
assertIn
(
'shared-part-list = %s'
%
self
.
shared_parts_root
,
software
.
error_log
)
def
test_remove_software
(
self
):
computer
=
ComputerForTest
(
self
.
software_root
,
self
.
instance_root
,
1
,
1
)
with
httmock
.
HTTMock
(
computer
.
request_handler
):
software
=
computer
.
software_list
[
0
]
software
.
setBuildout
(
"""#!/bin/sh
mkdir directory
touch directory/file
"""
)
self
.
launchSlapgridSoftware
()
self
.
assertIn
(
'directory'
,
os
.
listdir
(
os
.
path
.
join
(
self
.
software_root
,
software
.
software_hash
)))
software
.
requested_state
=
'destroyed'
self
.
launchSlapgridSoftware
()
self
.
assertEqual
(
os
.
listdir
(
self
.
software_root
),
[])
def
test_remove_software_chmod
(
self
):
# This software is "hard" to remove, as permissions have been changed
computer
=
ComputerForTest
(
self
.
software_root
,
self
.
instance_root
,
1
,
1
)
with
httmock
.
HTTMock
(
computer
.
request_handler
):
software
=
computer
.
software_list
[
0
]
software
.
setBuildout
(
"""#!/bin/sh
mkdir directory
touch directory/file
chmod a-rxw directory/file
chmod a-rxw directory
"""
)
self
.
launchSlapgridSoftware
()
self
.
assertIn
(
'directory'
,
os
.
listdir
(
os
.
path
.
join
(
self
.
software_root
,
software
.
software_hash
)))
software
.
requested_state
=
'destroyed'
self
.
launchSlapgridSoftware
()
self
.
assertEqual
(
os
.
listdir
(
self
.
software_root
),
[])
class
SlapgridInitialization
(
unittest
.
TestCase
):
"""
...
...
@@ -2397,6 +2682,8 @@ class TestSlapgridDestructionLock(MasterMixin, unittest.TestCase):
)))
instance
.
requested_state
=
'destroyed'
# Reset Cache
self
.
grid
.
computer_partition_list
=
None
self
.
grid
.
agregateAndSendUsage
()
self
.
assertTrue
(
os
.
path
.
exists
(
dummy_instance_file_path
))
self
.
assertTrue
(
os
.
path
.
exists
(
os
.
path
.
join
(
...
...
@@ -2850,28 +3137,30 @@ exit 0
[
'.slapgrid'
,
'.0_wrapper.log'
,
'buildout.cfg'
,
'etc'
,
'software_release'
,
'worked'
,
'.slapos-retention-lock-delay'
])
self
.
assertEqual
(
computer
.
sequence
,
[
'/getFullComputerInformation'
,
'/getComputerPartitionCertificate'
,
'/startedComputerPartition'
])
[
'/api/allDocs/'
,
'/api/get/'
,
'/api/put/'
])
self
.
assertEqual
(
partition
.
sequence
[
1
][
1
][
"reported_state"
],
'started'
)
self
.
assertEqual
(
partition
.
state
,
'started'
)
manager_list
=
slapmanager
.
from_config
({
'manager_list'
:
'prerm'
})
self
.
grid
.
_manager_list
=
manager_list
partition
.
requested_state
=
'destroyed'
self
.
grid
.
computer_partition_list
=
None
self
.
assertEqual
(
self
.
grid
.
agregateAndSendUsage
(),
slapgrid
.
SLAPGRID_SUCCESS
)
# Assert partition directory is not destroyed (pre-delete is running)
self
.
assertInstanceDirectoryListEqual
([
'0'
])
six
.
assertCountEqual
(
self
,
os
.
listdir
(
partition
.
partition_path
),
[
'.slapgrid'
,
'.0_wrapper.log'
,
'buildout.cfg'
,
'etc'
,
'software_release'
,
'worked'
,
'.slapos-retention-lock-delay'
,
'.0-prerm_slapos_pre_delete.log'
,
'.slapos-report-wait-service-list'
,
'.slapos-request-transaction-0'
])
'.0-prerm_slapos_pre_delete.log'
,
'.slapos-report-wait-service-list'
])
six
.
assertCountEqual
(
self
,
os
.
listdir
(
self
.
software_root
),
[
partition
.
software
.
software_hash
])
# wait until the pre-delete script is finished
self
.
_wait_prerm_script_finished
(
partition
.
partition_path
)
self
.
grid
.
computer_partition_list
=
None
self
.
assertEqual
(
self
.
grid
.
agregateAndSendUsage
(),
slapgrid
.
SLAPGRID_SUCCESS
)
# Assert partition directory is empty
self
.
assertInstanceDirectoryListEqual
([
'0'
])
...
...
@@ -2902,12 +3191,13 @@ exit 0
self
.
grid
.
_manager_list
=
manager_list
partition
.
requested_state
=
'destroyed'
self
.
grid
.
computer_partition_list
=
None
self
.
assertEqual
(
self
.
grid
.
agregateAndSendUsage
(),
slapgrid
.
SLAPGRID_SUCCESS
)
# Assert partition directory is not destroyed (retention-delay-lock)
six
.
assertCountEqual
(
self
,
os
.
listdir
(
partition
.
partition_path
),
[
'.slapgrid'
,
'buildout.cfg'
,
'etc'
,
'software_release'
,
'worked'
,
'.slapos-retention-lock-delay'
,
'.slapos-retention-lock-date'
,
'.slapos-request-transaction-0'
])
'.slapos-retention-lock-date'
])
self
.
assertTrue
(
os
.
path
.
exists
(
pre_delete_script
))
self
.
assertTrue
(
os
.
path
.
exists
(
os
.
path
.
join
(
partition
.
partition_path
,
...
...
@@ -2915,6 +3205,7 @@ exit 0
)))
time
.
sleep
(
1
)
self
.
grid
.
computer_partition_list
=
None
self
.
assertEqual
(
self
.
grid
.
agregateAndSendUsage
(),
slapgrid
.
SLAPGRID_SUCCESS
)
# Assert partition directory is not destroyed (pre-delete is running)
...
...
@@ -2922,7 +3213,7 @@ exit 0
[
'.slapgrid'
,
'buildout.cfg'
,
'etc'
,
'software_release'
,
'worked'
,
'.slapos-retention-lock-delay'
,
'.slapos-retention-lock-date'
,
'.0-prerm_slapos_pre_delete.log'
,
'.slapos-report-wait-service-list'
,
'.slapos-request-transaction-0'
])
])
# wait until the pre-delete script is finished
self
.
_wait_prerm_script_finished
(
partition
.
partition_path
)
...
...
@@ -2948,11 +3239,12 @@ exit 0
self
.
grid
.
_manager_list
=
manager_list
partition
.
requested_state
=
'destroyed'
self
.
grid
.
computer_partition_list
=
None
self
.
assertEqual
(
self
.
grid
.
agregateAndSendUsage
(),
slapgrid
.
SLAPGRID_SUCCESS
)
# Assert partition directory is not destroyed (pre-delete is running)
six
.
assertCountEqual
(
self
,
os
.
listdir
(
partition
.
partition_path
),
[
'.slapgrid'
,
'buildout.cfg'
,
'etc'
,
'software_release'
,
'worked'
,
'.slapos-retention-lock-delay'
,
'.slapos-request-transaction-0'
,
'worked'
,
'.slapos-retention-lock-delay'
,
'.0-prerm_slapos_pre_delete.log'
,
'.slapos-report-wait-service-list'
])
# wait until the pre-delete script is finished
...
...
@@ -2961,6 +3253,7 @@ exit 0
# the script is well finished...
self
.
assertTrue
(
"finished prerm script."
in
f
.
read
())
self
.
grid
.
computer_partition_list
=
None
self
.
assertEqual
(
self
.
grid
.
agregateAndSendUsage
(),
slapgrid
.
SLAPGRID_SUCCESS
)
# Assert partition directory is empty
self
.
assertInstanceDirectoryListEqual
([
'0'
])
...
...
@@ -2983,11 +3276,12 @@ exit 0
self
.
grid
.
_manager_list
=
manager_list
partition
.
requested_state
=
'destroyed'
self
.
grid
.
computer_partition_list
=
None
self
.
assertEqual
(
self
.
grid
.
agregateAndSendUsage
(),
slapgrid
.
SLAPGRID_SUCCESS
)
# Assert partition directory is not destroyed (pre-delete is running)
six
.
assertCountEqual
(
self
,
os
.
listdir
(
partition
.
partition_path
),
[
'.slapgrid'
,
'buildout.cfg'
,
'etc'
,
'software_release'
,
'worked'
,
'.slapos-retention-lock-delay'
,
'.slapos-request-transaction-0'
,
'worked'
,
'.slapos-retention-lock-delay'
,
'.0-prerm_slapos_pre_delete.log'
,
'.slapos-report-wait-service-list'
])
stat_info
=
os
.
stat
(
partition
.
partition_path
)
...
...
@@ -3013,6 +3307,7 @@ exit 0
# wait until the pre-delete script is finished
self._wait_prerm_script_finished(partition.partition_path)
self.grid.computer_partition_list = None
self.assertEqual(self.grid.agregateAndSendUsage(), slapgrid.SLAPGRID_SUCCESS)
# Assert partition directory is empty
self.assertInstanceDirectoryListEqual(['0'])
...
...
@@ -3056,6 +3351,73 @@ fdleak() {
: >&5 && fdleak 5
: >&6 && fdleak 6
echo "
file
descriptors
:
ok
"
exit 1 # do not proceed trying to use this software
""")
self.launchSlapgridSoftware()
self.assertEqual(
software.sequence,
[
(
'/api/put/',
{
'compute_node_id': self.computer_id,
'portal_type': 'Software Installation',
'reported_state': 'building',
'software_release_uri': software.name,
}
),
(
'/api/put/',
{
'compute_node_id': self.computer_id,
'portal_type': 'Software Installation',
'error_status': software.error_log,
'software_release_uri': software.name,
}
)
]
)
self.assertNotIn("
file
descriptors
:
leaked
", software.error_log)
self.assertIn("
file
descriptors
:
ok
", software.error_log)
class TestSlapgridNoFDLeakSlapTool(SlapToolMasterMixin, unittest.TestCase):
def test_no_fd_leak(self):
filev = []
try:
# open some file descriptors
for i in range(4):
f = open(os.devnull)
filev.append(f)
self.assertGreater(f.fileno(), 2)
# 'node software' with check that buildout does not see opened files
self._test_no_fd_leak()
finally:
for f in filev:
f.close()
def _test_no_fd_leak(self):
computer = ComputerForTest(self.software_root, self.instance_root, 1, 1)
with httmock.HTTMock(computer.request_handler):
software = computer.software_list[0]
software.setBuildout("""#!/bin/bash
fdleak() {
echo "
file
descriptors
:
leaked
:
" "
$
@
"
exit 1
}
# https://unix.stackexchange.com/a/206848
: >&3 && fdleak 3
: >&4 && fdleak 4
: >&5 && fdleak 5
: >&6 && fdleak 6
echo "
file
descriptors
:
ok
"
exit 1 # do not proceed trying to use this software
""")
...
...
@@ -3098,9 +3460,8 @@ class TestSlapgridWithPortRedirection(MasterMixin, unittest.TestCase):
self.assertEqual(self.grid.processComputerPartitionList(), slapgrid.SLAPGRID_SUCCESS)
self.assertEqual(self.computer.sequence,
['/getFullComputerInformation',
'/getComputerPartitionCertificate',
'/startedComputerPartition'])
['/api/allDocs/', '/api/get/', '/api/put/'])
self.assertEqual(self.partition.sequence[1][1]["
reported_state
"], 'started')
self.assertEqual(self.partition.state, 'started')
def test_simple_port_redirection(self):
...
...
@@ -3174,11 +3535,13 @@ class TestSlapgridWithPortRedirection(MasterMixin, unittest.TestCase):
self.assertEqual(self.grid.processComputerPartitionList(), slapgrid.SLAPGRID_SUCCESS)
self.assertEqual(self.computer.sequence,
['/getFullComputerInformation',
'/getComputerPartitionCertificate',
'/startedComputerPartition',
'/getComputerPartitionCertificate',
'/startedComputerPartition'])
['/api/allDocs/',
'/api/get/',
'/api/put/',
'/api/get/',
'/api/put/'])
self.assertEqual(self.partition.sequence[1][1]["
reported_state
"], 'started')
self.assertEqual(self.partition.sequence[3][1]["
reported_state
"], 'started')
self.assertEqual(self.partition.state, 'started')
# Check the socat command
...
...
@@ -3582,6 +3945,7 @@ class TestSlapgridWithWhitelistfirewall(MasterMixin, unittest.TestCase):
self.partition.requested_state = 'started'
self.partition.software.setBuildout(WRAPPER_CONTENT)
self.grid.computer_partition_list = None
self.assertEqual(self.grid.processComputerPartitionList(), slapgrid.SLAPGRID_SUCCESS)
self.assertEqual(
...
...
@@ -3600,6 +3964,7 @@ class TestSlapgridWithWhitelistfirewall(MasterMixin, unittest.TestCase):
self.partition.requested_state = 'started'
self.partition.software.setBuildout(WRAPPER_CONTENT)
self.grid.computer_partition_list = None
self.assertEqual(self.grid.processComputerPartitionList(), slapgrid.SLAPGRID_SUCCESS)
self.assertEqual(
...
...
@@ -3624,6 +3989,7 @@ class TestSlapgridWithWhitelistfirewall(MasterMixin, unittest.TestCase):
self.partition.requested_state = 'started'
self.partition.software.setBuildout(WRAPPER_CONTENT)
self.grid.computer_partition_list = None
self.assertEqual(self.grid.processComputerPartitionList(), slapgrid.SLAPGRID_SUCCESS)
self.assertEqual(
...
...
@@ -3708,6 +4074,7 @@ class TestSlapgridWithWhitelistfirewall(MasterMixin, unittest.TestCase):
self.partition.requested_state = 'destroyed'
self.partition.software.setBuildout(WRAPPER_CONTENT)
self.grid.computer_partition_list = None
self.assertEqual(self.grid.agregateAndSendUsage(), slapgrid.SLAPGRID_SUCCESS)
self.assertEqual(
...
...
@@ -3764,9 +4131,8 @@ class TestSlapgridManagerLifecycle(MasterMixin, unittest.TestCase):
self.assertEqual(self.grid.processComputerPartitionList(), slapgrid.SLAPGRID_SUCCESS)
self.assertEqual(self.computer.sequence,
['/getFullComputerInformation',
'/getComputerPartitionCertificate',
'/startedComputerPartition'])
['/api/allDocs/', '/api/get/', '/api/put/'])
self.assertEqual(partition.sequence[1][1]["
reported_state
"], 'started')
self.assertEqual(partition.state, 'started')
self.assertEqual(self.manager.sequence,
...
...
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