This repository has been archived by the owner on Oct 16, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 69
/
Copy pathBmapHelpers.py
152 lines (118 loc) · 4.29 KB
/
BmapHelpers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# -*- coding: utf-8 -*-
# vim: ts=4 sw=4 tw=88 et ai si
#
# Copyright (c) 2012-2014 Intel, Inc.
# License: GPLv2
# Author: Artem Bityutskiy <[email protected]>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2,
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
"""
This module contains various shared helper functions.
"""
import os
import struct
import subprocess
from fcntl import ioctl
from subprocess import PIPE
# Path to check for zfs compatibility.
ZFS_COMPAT_PARAM_PATH = "/sys/module/zfs/parameters/zfs_dmu_offset_next_sync"
class Error(Exception):
"""A class for all the other exceptions raised by this module."""
pass
def human_size(size):
"""Transform size in bytes into a human-readable form."""
if size == 1:
return "1 byte"
if size < 512:
return "%d bytes" % size
for modifier in ["KiB", "MiB", "GiB", "TiB"]:
size /= 1024.0
if size < 1024:
return "%.1f %s" % (size, modifier)
return "%.1f %s" % (size, "EiB")
def human_time(seconds):
"""Transform time in seconds to the HH:MM:SS format."""
(minutes, seconds) = divmod(seconds, 60)
(hours, minutes) = divmod(minutes, 60)
result = ""
if hours:
result = "%dh " % hours
if minutes:
result += "%dm " % minutes
return result + "%.1fs" % seconds
def get_block_size(file_obj):
"""
Return block size for file object 'file_obj'. Errors are indicated by the
'IOError' exception.
"""
# Get the block size of the host file-system for the image file by calling
# the FIGETBSZ ioctl (number 2).
try:
binary_data = ioctl(file_obj, 2, struct.pack("I", 0))
bsize = struct.unpack("I", binary_data)[0]
if not bsize:
raise IOError("get 0 bsize by FIGETBSZ ioctl")
except IOError as err:
stat = os.fstat(file_obj.fileno())
if hasattr(stat, "st_blksize"):
bsize = stat.st_blksize
else:
raise IOError("Unable to determine block size")
return bsize
def program_is_available(name):
"""
This is a helper function which check if the external program 'name' is
available in the system.
"""
for path in os.environ["PATH"].split(os.pathsep):
program = os.path.join(path.strip('"'), name)
if os.path.isfile(program) and os.access(program, os.X_OK):
return True
return False
def get_file_system_type(path):
"""Return the file system type for 'path'."""
abspath = os.path.realpath(path)
proc = subprocess.Popen(["df", "-T", "--", abspath], stdout=PIPE, stderr=PIPE)
stdout, stderr = proc.communicate()
# Parse the output of subprocess, for example:
# Filesystem Type 1K-blocks Used Available Use% Mounted on
# rpool/USERDATA/foo_5ucog2 zfs 456499712 86956288 369543424 20% /home/foo
ftype = None
if stdout:
lines = stdout.splitlines()
if len(lines) >= 2:
fields = lines[1].split(None, 2)
if len(fields) >= 2:
ftype = fields[1].lower()
if not ftype:
raise Error(
"failed to find file system type for path at '%s'\n"
"Here is the 'df -T' output\nstdout:\n%s\nstderr:\n%s"
% (path, stdout, stderr)
)
return ftype
def is_zfs_configuration_compatible():
"""Return if hosts zfs configuration is compatible."""
path = ZFS_COMPAT_PARAM_PATH
if not os.path.isfile(path):
return False
try:
with open(path, "r") as fobj:
return int(fobj.readline()) == 1
except IOError as err:
raise Error("cannot open zfs param path '%s': %s" % (path, err))
except ValueError as err:
raise Error("invalid value read from param path '%s': %s" % (path, err))
def is_compatible_file_system(path):
"""Return if paths file system is compatible."""
fstype = get_file_system_type(path)
if fstype == "zfs":
return is_zfs_configuration_compatible()
return True