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
Titouan Soulard
slapos.core
Commits
a999ce10
Commit
a999ce10
authored
Jul 15, 2022
by
Cédric Le Ninivin
Committed by
Titouan Soulard
Sep 18, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
slapos: Update slapgrid to use new API
parent
9b720767
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
868 additions
and
281 deletions
+868
-281
slapos/grid/SlapObject.py
slapos/grid/SlapObject.py
+28
-14
slapos/grid/slapgrid.py
slapos/grid/slapgrid.py
+282
-104
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 @
a999ce10
...
...
@@ -433,6 +433,7 @@ class Partition(object):
ipv4_global_network
=
''
,
buildout_debug
=
False
,
partition_timeout
=
None
,
api_backward_compatibility
=
False
,
):
"""Initialisation of class parameters"""
self
.
buildout
=
buildout
...
...
@@ -455,6 +456,7 @@ class Partition(object):
self
.
instance_storage_home
=
instance_storage_home
self
.
ipv4_global_network
=
ipv4_global_network
self
.
partition_timeout
=
partition_timeout
self
.
api_backward_compatibility
=
api_backward_compatibility
self
.
key_file
=
''
self
.
cert_file
=
''
...
...
@@ -501,16 +503,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
):
with
open
(
path
)
as
f
:
...
...
@@ -566,7 +572,7 @@ class Partition(object):
installs the software partition with the help of buildout
"""
self
.
logger
.
info
(
"Installing Computer Partition %s..."
%
self
.
partition_id
)
%
self
.
computer_partition
.
get
(
"compute_partition_id"
)
)
self
.
check_free_space
()
...
...
@@ -713,6 +719,14 @@ class Partition(object):
self
.
logger
.
warning
(
'No runners nor services found for partition %r'
%
self
.
partition_id
)
else
:
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
%
{
'instance_id'
:
partition_id
,
'program_list'
:
','
.
join
([
'_'
.
join
([
partition_id
,
runner
])
for
runner
in
runner_list
+
service_list
])
}
# Same method to add to service and run
self
.
addServicesToGroup
(
runner_list
,
self
.
run_path
)
self
.
addServicesToGroup
(
...
...
@@ -784,22 +798,22 @@ class Partition(object):
"""Asks supervisord to start the instance. If this instance is not
installed, we install it.
"""
self
.
updateSupervisorConfiguration
()
partition_id
=
self
.
partition_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..."
%
partition_id
)
self
.
logger
.
info
(
"Nothing to start on %s..."
%
self
.
computer_partition
.
get
(
"compute_partition_id"
))
else
:
raise
else
:
self
.
logger
.
info
(
"Requested start of %s..."
%
partition_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
.
partition_id
partition_id
=
self
.
computer_partition
.
get
(
"compute_partition_id"
)
filename
=
partition_id
+
'.conf'
filepath
=
os
.
path
.
join
(
self
.
supervisord_partition_configuration_dir
,
filename
)
...
...
@@ -810,13 +824,13 @@ class Partition(object):
raise
else
:
self
.
updateSupervisor
()
self
.
logger
.
info
(
"Requested stop of %s..."
%
partition_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
.
partition_id
)
%
self
.
computer_partition
.
get
(
"compute_partition_id"
)
)
self
.
createRetentionLockDate
()
if
not
self
.
checkRetentionIsAuthorized
():
...
...
slapos/grid/slapgrid.py
View file @
a999ce10
...
...
@@ -383,6 +383,7 @@ class Slapgrid(object):
shared_part_list
=
''
,
force_stop
=
False
,
partition_timeout
=
None
,
slapgrid_jio_uri
=
None
,
):
"""Makes easy initialisation of class parameters"""
# Parses arguments
...
...
@@ -417,10 +418,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
...
...
@@ -437,6 +444,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
...
...
@@ -571,22 +579,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
):
...
...
@@ -596,10 +644,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
,
...
...
@@ -641,7 +706,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
()
...
...
@@ -658,14 +731,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
:
...
...
@@ -674,17 +765,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.'
)
...
...
@@ -778,7 +895,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
,
...
...
@@ -787,9 +904,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 "
\
...
...
@@ -1000,7 +1124,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
:
...
...
@@ -1009,7 +1149,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
:
...
...
@@ -1029,11 +1169,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
...
...
@@ -1045,17 +1185,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
...
...
@@ -1064,12 +1211,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
))
...
...
@@ -1078,7 +1220,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
,
...
...
@@ -1096,10 +1238,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
)
...
...
@@ -1115,7 +1258,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
...
...
@@ -1139,20 +1282,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
:
...
...
@@ -1160,7 +1297,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'
)
...
...
@@ -1188,7 +1325,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
,
...
...
@@ -1269,7 +1406,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
):
...
...
@@ -1277,7 +1414,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
:
...
...
@@ -1291,7 +1428,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
:
...
...
@@ -1305,9 +1449,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
...
...
@@ -1319,16 +1470,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
):
...
...
@@ -1364,7 +1522,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
)
...
...
@@ -1373,11 +1531,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
...
...
@@ -1395,7 +1550,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
...
...
@@ -1405,7 +1560,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
:
...
...
@@ -1414,7 +1569,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
:
...
...
@@ -1451,6 +1606,11 @@ 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
)
...
...
@@ -1461,14 +1621,14 @@ 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
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
...
...
@@ -1482,7 +1642,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
...
...
@@ -1492,9 +1652,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.'
)
...
...
@@ -1502,11 +1661,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
:
...
...
@@ -1541,6 +1700,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
)
...
...
@@ -1556,15 +1720,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
:
...
...
@@ -1657,7 +1820,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...'
)
...
...
@@ -1687,11 +1849,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
)
...
...
@@ -1728,18 +1890,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'
,
...
...
@@ -1784,7 +1946,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'
%
...
...
@@ -1810,7 +1972,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
)
...
...
@@ -1830,37 +1992,39 @@ 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"
)),
shared_part_list
=
self
.
shared_part_list
,
supervisord_partition_configuration_dir
=
(
_getSupervisordConfigurationDirectory
(
self
.
instance_root
)),
supervisord_partition_configuration_path
=
os
.
path
.
join
(
_getSupervisordConfigurationDirectory
(
self
.
instance_root
),
'%s.conf'
%
computer_partition_id
),
supervisord_socket
=
self
.
supervisord_socket
,
computer_partition
=
computer_partition
,
computer_id
=
self
.
computer_id
,
...
...
@@ -1877,9 +2041,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
...
...
@@ -1887,9 +2058,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'
]):
...
...
@@ -1898,24 +2069,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 @
a999ce10
...
...
@@ -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 @
a999ce10
...
...
@@ -762,6 +762,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
):
...
...
@@ -770,7 +800,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 @
a999ce10
...
...
@@ -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
):
"""
...
...
@@ -394,6 +420,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
...
...
@@ -423,6 +450,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
])
...
...
@@ -559,6 +743,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
,
):
"""
...
...
@@ -567,8 +755,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
}
...
...
@@ -626,12 +813,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
)
...
...
@@ -737,11 +922,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
):
"""
...
...
@@ -758,9 +941,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
):
"""
...
...
@@ -793,9 +976,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
):
...
...
@@ -813,9 +995,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
]
...
...
@@ -829,14 +1010,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
)
...
...
@@ -873,9 +1051,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
=
[]
...
...
@@ -888,9 +1065,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
):
...
...
@@ -934,9 +1110,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
=
[]
...
...
@@ -953,10 +1130,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
)
...
...
@@ -973,9 +1152,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'
...
...
@@ -992,9 +1172,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
):
...
...
@@ -1018,9 +1199,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
)
def
test_one_partition_started_no_master
(
self
):
...
...
@@ -1473,8 +1655,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
)
...
...
@@ -1495,9 +1677,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
)
...
...
@@ -1514,8 +1697,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
)
...
...
@@ -1533,17 +1716,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
)
...
...
@@ -1561,15 +1737,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
):
"""
...
...
@@ -1634,17 +1805,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
)
...
...
@@ -1674,16 +1845,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
)
...
...
@@ -1714,17 +1886,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
)
...
...
@@ -1788,10 +1962,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
):
"""
...
...
@@ -1805,10 +1984,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
):
"""
...
...
@@ -1822,10 +2006,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
):
"""
...
...
@@ -1839,10 +2025,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
):
"""
...
...
@@ -1858,7 +2046,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
)
...
...
@@ -1941,7 +2130,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/"
)
def
test_supervisor_partition_files_removed_on_stop
(
self
):
computer
=
self
.
getTestComputerClass
()(
self
.
software_root
,
self
.
instance_root
,
2
,
1
)
...
...
@@ -2011,14 +2201,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'
])
...
...
@@ -2030,10 +2224,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
):
...
...
@@ -2051,6 +2246,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'
])
...
...
@@ -2061,12 +2257,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
):
"""
...
...
@@ -2086,33 +2283,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
):
...
...
@@ -2132,7 +2328,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
):
"""
...
...
@@ -2151,10 +2347,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
):
...
...
@@ -2223,6 +2419,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
):
"""
...
...
@@ -2506,6 +2791,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
(
...
...
@@ -2959,28 +3246,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'
])
...
...
@@ -3011,12 +3300,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
,
...
...
@@ -3024,6 +3314,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)
...
...
@@ -3031,7 +3322,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
)
...
...
@@ -3057,11 +3348,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
...
...
@@ -3070,6 +3362,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'
])
...
...
@@ -3092,11 +3385,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
)
...
...
@@ -3126,6 +3420,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'])
...
...
@@ -3169,6 +3464,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
""")
...
...
@@ -3211,9 +3573,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):
...
...
@@ -3287,11 +3648,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
...
...
@@ -3673,6 +4036,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(
...
...
@@ -3691,6 +4055,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(
...
...
@@ -3715,6 +4080,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(
...
...
@@ -3799,6 +4165,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(
...
...
@@ -3855,9 +4222,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