Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
V
vospace-transfer-service
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
VOSpace INAF
vospace-transfer-service
Commits
fd20eba6
Commit
fd20eba6
authored
Aug 23, 2021
by
Cristiano Urban
Browse files
Options
Downloads
Patches
Plain Diff
Added basic exception handling + improved logging.
Signed-off-by:
Cristiano Urban
<
cristiano.urban@inaf.it
>
parent
7a3c7971
No related branches found
No related tags found
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
transfer_service/exceptions.py
+14
-1
14 additions, 1 deletion
transfer_service/exceptions.py
transfer_service/tape_client.py
+163
-108
163 additions, 108 deletions
transfer_service/tape_client.py
with
177 additions
and
109 deletions
transfer_service/exceptions.py
+
14
−
1
View file @
fd20eba6
...
...
@@ -10,7 +10,7 @@ class Error(Exception):
class
TarFileCreationException
(
Error
):
def
__init__
(
self
,
folder
):
self
.
message
=
"
Error: cannot create a .tar for
"
+
folder
super
(
MultipleUsers
Exception
,
self
).
__init__
(
self
.
message
)
super
(
TarFileCreation
Exception
,
self
).
__init__
(
self
.
message
)
# RapClient exceptions
...
...
@@ -19,3 +19,16 @@ class MultipleUsersException(Error):
def
__init__
(
self
):
self
.
message
=
"
Multiple users found with the same email address.
"
super
(
MultipleUsersException
,
self
).
__init__
(
self
.
message
)
# TapeClient exceptions
class
TapeClientException
(
Error
):
def
__init__
(
self
,
cmd
,
exitCode
,
errorMsg
):
self
.
message
=
f
"
{
cmd
}
\n
exitCode:
{
exitCode
}
\n
errorMsg:
{
errorMsg
}
\n
"
super
(
TapeClientException
,
self
).
__init__
(
self
.
message
)
class
ScpInvalidFileException
(
Error
):
def
__init__
(
self
):
self
.
message
=
"
Error: invalid file or directory.
"
super
(
ScpInvalidFileException
,
self
).
__init__
(
self
.
message
)
This diff is collapsed.
Click to expand it.
transfer_service/tape_client.py
+
163
−
108
View file @
fd20eba6
...
...
@@ -9,15 +9,17 @@ import sys
import
uuid
from
config
import
Config
from
exceptions
import
ScpInvalidFileException
from
exceptions
import
TapeClientException
from
redis_log_handler
import
RedisLogHandler
from
tape_pool
import
TapePool
from
tape_task
import
TapeTask
class
TapeClient
(
object
):
# 'eeadm' command location on the tape library frontend
EEADM
=
"
/opt/ibm/ltfsee/bin/eeadm
"
# Constructor
def
__init__
(
self
,
host
,
port
,
user
,
keyFile
,
logger
):
self
.
host
=
host
self
.
port
=
port
...
...
@@ -25,22 +27,37 @@ class TapeClient(object):
self
.
logger
=
logger
self
.
client
=
paramiko
.
SSHClient
()
self
.
client
.
set_missing_host_key_policy
(
paramiko
.
AutoAddPolicy
())
self
.
key
=
paramiko
.
RSAKey
.
from_private_key_file
(
keyFile
)
self
.
client
.
load_system_host_keys
()
self
.
keyFile
=
keyFile
#self.key = paramiko.RSAKey.from_private_key_file(keyFile)
#self.client.load_system_host_keys()
self
.
scp
=
None
self
.
taskList
=
[]
self
.
poolList
=
[]
def
connect
(
self
):
"""
Connects to the tape library frontend.
"""
try
:
self
.
key
=
paramiko
.
RSAKey
.
from_private_key_file
(
self
.
keyFile
)
self
.
client
.
load_system_host_keys
()
self
.
client
.
connect
(
hostname
=
self
.
host
,
port
=
self
.
port
,
username
=
self
.
user
,
pkey
=
self
.
key
)
except
Exception
:
self
.
logger
.
exception
(
"
Unable to establish SSH connection with tape library frontend.
"
)
raise
finally
:
self
.
client
.
disconnect
()
def
getPoolList
(
self
):
"""
Returns a list of
'
TapePool
'
objects.
"""
stdin
,
stdout
,
stderr
=
self
.
client
.
exec_command
(
f
"
{
self
.
EEADM
}
pool list --json
"
)
cmd
=
f
"
{
self
.
EEADM
}
pool list --json
"
try
:
stdin
,
stdout
,
stderr
=
self
.
client
.
exec_command
(
cmd
)
except
Exception
:
self
.
logger
.
exception
(
"
Unable to execute command:
'
{cmd}
'"
)
raise
else
:
exitCode
=
stdout
.
channel
.
recv_exit_status
()
if
not
exitCode
:
result
=
json
.
loads
(
stdout
.
readlines
()[
0
].
rstrip
(
'
\n
'
))
...
...
@@ -72,17 +89,20 @@ class TapeClient(object):
self
.
poolList
.
append
(
pool
)
return
self
.
poolList
.
copy
()
else
:
sys
.
exit
(
"
cmd
_
exit
_c
ode
= FAILURE
"
)
raise
TapeClientException
(
cmd
,
exit
C
ode
,
stderr
)
def
getTaskList
(
self
):
"""
Returns the whole task list.
"""
stdin
,
stdout
,
stderr
=
self
.
client
.
exec_command
(
f
"
{
self
.
EEADM
}
task list --json
"
)
cmd
=
f
"
{
self
.
EEADM
}
task list --json
"
try
:
stdin
,
stdout
,
stderr
=
self
.
client
.
exec_command
(
cmd
)
except
Exception
:
self
.
logger
.
exception
(
"
Unable to execute command:
'
{cmd}
'"
)
raise
else
:
exitCode
=
stdout
.
channel
.
recv_exit_status
()
if
not
exitCode
:
result
=
json
.
loads
(
stdout
.
readlines
()[
0
].
rstrip
(
'
\n
'
))
#print(result)
#print(len(result["payload"]))
#print(result["payload"][0])
for
el
in
result
[
"
payload
"
]:
task
=
TapeTask
()
task
.
inUseTapes
=
el
[
"
inuse_tapes
"
]
...
...
@@ -102,18 +122,25 @@ class TapeClient(object):
self
.
taskList
.
append
(
task
)
return
self
.
taskList
.
copy
()
else
:
sys
.
exit
(
"
cmd
_
exit
_c
ode
= FAILURE
"
)
raise
TapeClientException
(
cmd
,
exit
C
ode
,
stderr
)
def
copy
(
self
,
srcPath
,
destPath
):
"""
Copies files/dirs recursively by passing their absolute paths.
"""
try
:
self
.
scp
=
scp
.
SCPClient
(
self
.
client
.
get_transport
())
print
(
f
"
Copying
{
srcPath
}
in
{
destPath
}
"
)
except
Exception
:
self
.
logger
.
error
(
"
Unable to get transport from SSH client.
"
)
raise
else
:
self
.
logger
.
debug
(
f
"
Copying
{
srcPath
}
in
{
destPath
}
"
)
if
os
.
path
.
isdir
(
srcPath
):
self
.
scp
.
put
(
srcPath
,
recursive
=
True
,
remote_path
=
destPath
)
elif
os
.
path
.
isfile
(
srcPath
):
self
.
scp
.
put
(
srcPath
,
destPath
)
else
:
sys
.
exit
(
"
FATAL: invalid file/dir.
"
)
self
.
logger
.
error
(
"
FATAL: invalid file/dir.
"
)
raise
ScpInvalidFileException
finally
:
self
.
scp
.
close
()
def
migrate
(
self
,
fileList
,
tapePool
):
...
...
@@ -121,58 +148,86 @@ class TapeClient(object):
Migrates to tape all files whose absolute path is
contained in
'
fileList
'
.
"""
self
.
logger
.
debug
(
"
Starting MIGRATE operation...
"
)
self
.
logger
.
info
(
"
Starting MIGRATE operation...
"
)
tmp
=
str
(
uuid
.
uuid1
().
hex
)
+
"
-vos_migrate.tmp
"
try
:
fp
=
open
(
tmp
,
"
a
"
)
except
IOError
:
raise
else
:
for
f
in
fileList
:
fp
.
write
(
f
"
{
f
}
\n
"
)
fp
.
close
()
self
.
copy
(
f
"
./
{
tmp
}
"
,
f
"
/tmp/
{
tmp
}
"
)
os
.
remove
(
f
"
./
{
tmp
}
"
)
cmd
=
f
"
{
self
.
EEADM
}
migrate /tmp/
{
tmp
}
-p
{
tapePool
}
"
try
:
stdin
,
stdout
,
stderr
=
self
.
client
.
exec_command
(
cmd
)
except
Exception
:
self
.
logger
.
exception
(
"
Unable to execute command:
'
{cmd}
'"
)
raise
else
:
exitCode
=
stdout
.
channel
.
recv_exit_status
()
if
not
exitCode
:
self
.
logger
.
debug
(
"
MIGRATE operation COMPLETED.
"
)
self
.
logger
.
info
(
"
MIGRATE operation COMPLETED.
"
)
else
:
self
.
logger
.
debug
(
"
MIGRATE operation FAILED.
"
)
self
.
logger
.
error
(
"
MIGRATE operation FAILED.
"
)
raise
TapeClientException
(
cmd
,
exitCode
,
stderr
)
return
exitCode
finally
:
fp
.
close
()
def
recall
(
self
,
fileList
):
"""
Recalls from tape all files whose absolute path is
contained in
'
fileList
'
.
"""
self
.
logger
.
debug
(
"
Starting RECALL operation...
"
)
self
.
logger
.
info
(
"
Starting RECALL operation...
"
)
tmp
=
str
(
uuid
.
uuid1
().
hex
)
+
"
-vos_recall.tmp
"
try
:
fp
=
open
(
tmp
,
"
a
"
)
except
IOError
:
raise
else
:
for
f
in
fileList
:
fp
.
write
(
f
"
{
f
}
\n
"
)
fp
.
close
()
self
.
copy
(
f
"
./
{
tmp
}
"
,
f
"
/tmp/
{
tmp
}
"
)
os
.
remove
(
f
"
./
{
tmp
}
"
)
cmd
=
f
"
{
self
.
EEADM
}
recall /tmp/
{
tmp
}
"
try
:
stdin
,
stdout
,
stderr
=
self
.
client
.
exec_command
(
cmd
)
except
Exception
:
self
.
logger
.
exception
(
"
Unable to execute command:
'
{cmd}
'"
)
raise
else
:
exitCode
=
stdout
.
channel
.
recv_exit_status
()
if
not
exitCode
:
self
.
logger
.
debug
(
"
RECALL operation COMPLETED.
"
)
self
.
logger
.
info
(
"
RECALL operation COMPLETED.
"
)
else
:
self
.
logger
.
debug
(
"
RECALL operation FAILED.
"
)
self
.
logger
.
error
(
"
RECALL operation FAILED.
"
)
raise
TapeClientException
(
cmd
,
exitCode
,
stderr
)
return
exitCode
finally
:
fp
.
close
()
def
recallChecksumFiles
(
self
,
dirName
):
"""
Recursively recalls from tape all the checksum files related to
the
'
dirName
'
directory.
"""
self
.
logger
.
debug
(
"
Starting RECALL_CHECKSUM operation...
"
)
self
.
logger
.
info
(
"
Starting RECALL_CHECKSUM operation...
"
)
cmd
=
f
"
find $(dirname
{
dirName
}
) -type f \( -iname
\"
*-md5sum.txt
\"
\) |
{
self
.
EEADM
}
recall
"
try
:
stdin
,
stdout
,
stderr
=
self
.
client
.
exec_command
(
cmd
)
except
Exception
:
self
.
logger
.
exception
(
"
Unable to execute command:
'
{cmd}
'"
)
raise
else
:
exitCode
=
stdout
.
channel
.
recv_exit_status
()
if
not
exitCode
:
self
.
logger
.
debug
(
"
RECALL_CHECKSUM operation COMPLETED.
"
)
self
.
logger
.
info
(
"
RECALL_CHECKSUM operation COMPLETED.
"
)
else
:
self
.
logger
.
debug
(
"
RECALL_CHECKSUM operation FAILED.
"
)
self
.
logger
.
error
(
"
RECALL_CHECKSUM operation FAILED.
"
)
raise
TapeClientException
(
cmd
,
exitCode
,
stderr
)
return
exitCode
def
disconnect
(
self
):
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment