Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
lvm-snapshots
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
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
infra
lvm-snapshots
Commits
58f0cd02
Commit
58f0cd02
authored
8 years ago
by
Administrator
Browse files
Options
Downloads
Patches
Plain Diff
Add commands, argument parsing
parent
5601b740
No related branches found
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
lvmsnapshot.py
+62
-14
62 additions, 14 deletions
lvmsnapshot.py
with
62 additions
and
14 deletions
lvmsnapshot.py
+
62
−
14
View file @
58f0cd02
...
@@ -22,6 +22,7 @@
...
@@ -22,6 +22,7 @@
# mark snapshots to keep, from oldest within period to new
# mark snapshots to keep, from oldest within period to new
# delete unmarked snapshots
# delete unmarked snapshots
import
logging
import
os
import
os
import
re
import
re
from
datetime
import
datetime
,
timedelta
from
datetime
import
datetime
,
timedelta
...
@@ -40,6 +41,14 @@ PERIOD_KEYS = OrderedDict([
...
@@ -40,6 +41,14 @@ PERIOD_KEYS = OrderedDict([
(
"
M
"
,
60
),
(
"
M
"
,
60
),
])
])
def
run_process
(
command
,
check
=
True
):
result
=
sp
.
run
(
command
,
check
=
check
,
stdout
=
sp
.
PIPE
,
stderr
=
sp
.
PIPE
)
if
result
.
stdout
:
logging
.
info
(
result
.
stdout
.
decode
(
"
utf-8
"
).
strip
())
if
result
.
stderr
:
logging
.
warn
(
result
.
stderr
.
decode
(
"
utf-8
"
).
strip
())
return
result
@contextmanager
@contextmanager
def
xfs_freeze
(
mountpoint
):
def
xfs_freeze
(
mountpoint
):
freeze_xfs
(
mountpoint
,
True
)
freeze_xfs
(
mountpoint
,
True
)
...
@@ -52,7 +61,7 @@ def freeze_xfs(mountpoint, freeze):
...
@@ -52,7 +61,7 @@ def freeze_xfs(mountpoint, freeze):
"
-f
"
if
freeze
else
"
-u
"
,
"
-f
"
if
freeze
else
"
-u
"
,
mountpoint
mountpoint
]
]
sp
.
run
(
command
,
check
=
True
)
run
_process
(
command
,
check
=
True
)
class
Volume
:
class
Volume
:
def
__init__
(
self
,
volume_group
,
name
):
def
__init__
(
self
,
volume_group
,
name
):
...
@@ -149,17 +158,19 @@ class Snapshot:
...
@@ -149,17 +158,19 @@ class Snapshot:
"
--permission
"
,
"
r
"
,
"
--permission
"
,
"
r
"
,
self
.
parent_volume
.
get_full_name
()
self
.
parent_volume
.
get_full_name
()
]
]
sp
.
run
(
create_command
,
check
=
True
)
run
_process
(
create_command
,
check
=
True
)
self
.
mount
()
self
.
mount
()
def
mount
(
self
):
def
mount
(
self
):
if
self
.
check_mount
():
return
activate_command
=
[
activate_command
=
[
"
/sbin/lvchange
"
,
"
/sbin/lvchange
"
,
"
--activate
"
,
"
y
"
,
"
--activate
"
,
"
y
"
,
"
--ignoreactivationskip
"
,
"
--ignoreactivationskip
"
,
self
.
get_full_volume
()
self
.
get_full_volume
()
]
]
sp
.
run
(
activate_command
,
check
=
True
)
run
_process
(
activate_command
,
check
=
True
)
self
.
active
=
True
self
.
active
=
True
self
.
create_mountpoint
()
self
.
create_mountpoint
()
mount_command
=
[
mount_command
=
[
...
@@ -168,7 +179,7 @@ class Snapshot:
...
@@ -168,7 +179,7 @@ class Snapshot:
self
.
get_mountpoint
(),
self
.
get_mountpoint
(),
"
-o
"
,
self
.
get_mount_options
()
"
-o
"
,
self
.
get_mount_options
()
]
]
sp
.
run
(
mount_command
,
check
=
True
)
run
_process
(
mount_command
,
check
=
True
)
def
check_mount
(
self
):
def
check_mount
(
self
):
check_command
=
[
check_command
=
[
...
@@ -176,7 +187,7 @@ class Snapshot:
...
@@ -176,7 +187,7 @@ class Snapshot:
"
--source
"
,
self
.
get_mapper_device
()
"
--source
"
,
self
.
get_mapper_device
()
]
]
try
:
try
:
sp
.
check_call
(
check_command
)
sp
.
check_call
(
check_command
,
stdout
=
sp
.
DEVNULL
,
stderr
=
sp
.
DEVNULL
)
return
True
return
True
except
sp
.
CalledProcessError
:
except
sp
.
CalledProcessError
:
return
False
return
False
...
@@ -187,7 +198,7 @@ class Snapshot:
...
@@ -187,7 +198,7 @@ class Snapshot:
"
/sbin/lvremove
"
,
"
/sbin/lvremove
"
,
self
.
get_full_volume
()
self
.
get_full_volume
()
]
]
sp
.
run
(
remove_command
,
check
=
True
)
run
_process
(
remove_command
,
check
=
True
)
def
unmount
(
self
):
def
unmount
(
self
):
if
self
.
check_mount
():
if
self
.
check_mount
():
...
@@ -195,14 +206,14 @@ class Snapshot:
...
@@ -195,14 +206,14 @@ class Snapshot:
"
/bin/umount
"
,
"
/bin/umount
"
,
self
.
get_mountpoint
()
self
.
get_mountpoint
()
]
]
sp
.
run
(
unmount_command
,
check
=
True
)
run
_process
(
unmount_command
,
check
=
True
)
deactivate_command
=
[
deactivate_command
=
[
"
/sbin/lvchange
"
,
"
/sbin/lvchange
"
,
"
--activate
"
,
"
n
"
,
"
--activate
"
,
"
n
"
,
"
--ignoreactivationskip
"
,
"
--ignoreactivationskip
"
,
self
.
get_full_volume
()
self
.
get_full_volume
()
]
]
sp
.
run
(
deactivate_command
,
check
=
True
)
run
_process
(
deactivate_command
,
check
=
True
)
self
.
active
=
False
self
.
active
=
False
os
.
rmdir
(
self
.
get_mountpoint
())
os
.
rmdir
(
self
.
get_mountpoint
())
...
@@ -287,11 +298,12 @@ def load_config():
...
@@ -287,11 +298,12 @@ def load_config():
import
sys
import
sys
import
toml
import
toml
config_path
=
"
config.toml
"
config_path
=
"
config.toml
"
global_config_path
=
"
/etc/lvm-snapshot.toml
"
ENV_VAR
=
"
LVM_SNAPSHOT_CONFIG
"
ENV_VAR
=
"
LVM_SNAPSHOT_CONFIG
"
if
not
os
.
path
.
isfile
(
config_path
)
and
os
.
path
.
isfile
(
global_config_path
):
config_path
=
global_config_path
if
ENV_VAR
in
os
.
environ
:
if
ENV_VAR
in
os
.
environ
:
config_path
=
os
.
environ
[
ENV_VAR
]
config_path
=
os
.
environ
[
ENV_VAR
]
if
len
(
sys
.
argv
)
>
1
:
config_path
=
sys
.
argv
[
1
]
with
open
(
config_path
,
"
r
"
)
as
config_file
:
with
open
(
config_path
,
"
r
"
)
as
config_file
:
return
toml
.
load
(
config_file
)
return
toml
.
load
(
config_file
)
...
@@ -330,23 +342,59 @@ def mark_snapshots(snapshots, periods, min_interval):
...
@@ -330,23 +342,59 @@ def mark_snapshots(snapshots, periods, min_interval):
unmarked_snapshots
=
all_snapshots
-
marked_snapshots
unmarked_snapshots
=
all_snapshots
-
marked_snapshots
return
unmarked_snapshots
return
unmarked_snapshots
def
main
():
def
list_snapshots
(
**
kwargs
):
snapshots
=
Snapshot
.
list_snapshots
()
for
volume
in
snapshots
:
print
(
"
volume: {}
"
.
format
(
str
(
volume
)))
for
snapshot
in
snapshots
[
volume
]:
print
(
"
{}
"
.
format
(
str
(
snapshot
)))
def
mount_snapshots
(
**
kwargs
):
snapshots
=
Snapshot
.
list_snapshots
()
for
volume
in
snapshots
:
for
snapshot
in
snapshots
[
volume
]:
snapshot
.
mount
()
def
unmount_snapshots
(
**
kwargs
):
snapshots
=
Snapshot
.
list_snapshots
()
for
volume
in
snapshots
:
for
snapshot
in
snapshots
[
volume
]:
snapshot
.
unmount
()
def
update_snapshots
():
config
=
load_config
()
config
=
load_config
()
snapshots
=
Snapshot
.
list_snapshots
()
snapshots
=
Snapshot
.
list_snapshots
()
periods
,
min_interval
=
parse_config
(
config
)
periods
,
min_interval
=
parse_config
(
config
)
for
volume
in
set
(
periods
.
keys
())
-
set
(
snapshots
.
keys
()):
for
volume
in
set
(
periods
.
keys
())
-
set
(
snapshots
.
keys
()):
print
(
"
Warning: Volume {} is configured but does not exist or has no snapshots.
"
.
format
(
volume
))
logging
.
warn
(
"
Warning: Volume {} is configured but does not exist or has no snapshots.
"
.
format
(
volume
))
for
volume
in
set
(
snapshots
.
keys
())
-
set
(
periods
.
keys
()):
for
volume
in
set
(
snapshots
.
keys
())
-
set
(
periods
.
keys
()):
print
(
"
Warning: Volume {} does exist but is not configured.
"
.
format
(
volume
))
logging
.
warn
(
"
Warning: Volume {} does exist but is not configured.
"
.
format
(
volume
))
snapshots
.
pop
(
volume
)
snapshots
.
pop
(
volume
)
for
volume
in
snapshots
:
for
volume
in
snapshots
:
unmarked_snapshots
=
mark_snapshots
(
snapshots
[
volume
],
periods
[
volume
],
min_interval
)
unmarked_snapshots
=
mark_snapshots
(
snapshots
[
volume
],
periods
[
volume
],
min_interval
)
print
(
"
removing
"
,
unmarked_snapshots
)
for
snapshot
in
unmarked_snapshots
:
for
snapshot
in
unmarked_snapshots
:
snapshot
.
remove
()
snapshot
.
remove
()
new_snapshot
=
Snapshot
(
volume
,
datetime
.
now
())
new_snapshot
=
Snapshot
(
volume
,
datetime
.
now
())
new_snapshot
.
create
()
new_snapshot
.
create
()
operations
=
{
"
list
"
:
list_snapshots
,
"
update
"
:
update_snapshots
,
"
mount
"
:
mount_snapshots
,
"
unmount
"
:
unmount_snapshots
,
}
def
main
():
import
argparse
parser
=
argparse
.
ArgumentParser
()
parser
.
add_argument
(
"
command
"
,
help
=
"
list|update|mount|unmount
"
)
parser
.
add_argument
(
"
--verbose
"
,
action
=
"
store_true
"
,
help
=
"
do not redirect the command output to /dev/null
"
)
args
=
parser
.
parse_args
()
loglevel
=
logging
.
ERROR
if
args
.
verbose
:
loglevel
=
logging
.
INFO
logging
.
basicConfig
(
level
=
loglevel
)
operations
[
args
.
command
]()
if
__name__
==
"
__main__
"
:
if
__name__
==
"
__main__
"
:
main
()
main
()
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