]>
git.proxmox.com Git - ceph.git/blob - ceph/src/ceph-volume/ceph_volume/util/system.py
8 from ceph_volume
import process
, terminal
9 from . import as_string
11 logger
= logging
.getLogger(__name__
)
12 mlogger
= terminal
.MultiLogger(__name__
)
14 # TODO: get these out of here and into a common area for others to consume
15 if platform
.system() == 'FreeBSD':
17 DEFAULT_FS_TYPE
= 'zfs'
18 PROCDIR
= '/compat/linux/proc'
19 # FreeBSD does not have blockdevices any more
24 DEFAULT_FS_TYPE
= 'xfs'
26 BLOCKDIR
= '/sys/block'
31 return str(uuid
.uuid4())
34 def which(executable
):
35 """find the location of an executable"""
45 for location
in locations
:
46 executable_path
= os
.path
.join(location
, executable
)
47 if os
.path
.exists(executable_path
) and os
.path
.isfile(executable_path
):
48 return executable_path
49 mlogger
.warning('Absolute path not found for executable: %s', executable
)
50 mlogger
.warning('Ensure $PATH environment variable contains common executable locations')
51 # fallback to just returning the argument as-is, to prevent a hard fail,
52 # and hoping that the system might have the executable somewhere custom
56 def get_ceph_user_ids():
58 Return the id and gid of the ceph user
61 user
= pwd
.getpwnam('ceph')
63 # is this even possible?
64 raise RuntimeError('"ceph" user is not available in the current system')
65 return user
[2], user
[3]
68 def mkdir_p(path
, chown
=True):
70 A `mkdir -p` that defaults to chown the path to the ceph user
75 if e
.errno
== errno
.EEXIST
:
80 uid
, gid
= get_ceph_user_ids()
81 os
.chown(path
, uid
, gid
)
84 def chown(path
, recursive
=True):
86 ``chown`` a path to the ceph user (uid and guid fetched at runtime)
88 uid
, gid
= get_ceph_user_ids()
89 if os
.path
.islink(path
):
90 process
.run(['chown', '-h', 'ceph:ceph', path
])
91 path
= os
.path
.realpath(path
)
93 process
.run(['chown', '-R', 'ceph:ceph', path
])
95 os
.chown(path
, uid
, gid
)
100 Detect if a file path is a binary or not. Will falsely report as binary
101 when utf-16 encoded. In the ceph universe there is no such risk (yet)
103 with
open(path
, 'rb') as fp
:
104 contents
= fp
.read(8192)
105 if b
'\x00' in contents
: # a null byte may signal binary
110 class tmp_mount(object):
112 Temporarily mount a device on a temporary directory,
113 and unmount it upon exit
115 When ``encrypted`` is set to ``True``, the exit method will call out to
116 close the device so that it doesn't remain open after mounting. It is
117 assumed that it will be open because otherwise it wouldn't be possible to
118 mount in the first place
121 def __init__(self
, device
, encrypted
=False):
124 self
.encrypted
= encrypted
127 self
.path
= tempfile
.mkdtemp()
136 def __exit__(self
, exc_type
, exc_val
, exc_tb
):
143 # avoid a circular import from the encryption module
144 from ceph_volume
.util
import encryption
145 encryption
.dmcrypt_close(self
.device
)
150 Removes mounts at the given path
159 def path_is_mounted(path
, destination
=None):
161 Check if the given path is mounted
163 mounts
= get_mounts(paths
=True)
164 realpath
= os
.path
.realpath(path
)
165 mounted_locations
= mounts
.get(realpath
, [])
168 return destination
in mounted_locations
169 return mounted_locations
!= []
172 def device_is_mounted(dev
, destination
=None):
174 Check if the given device is mounted, optionally validating that a
177 plain_mounts
= get_mounts(devices
=True)
178 realpath_mounts
= get_mounts(devices
=True, realpath
=True)
179 realpath_dev
= os
.path
.realpath(dev
) if dev
.startswith('/') else dev
180 destination
= os
.path
.realpath(destination
) if destination
else None
182 plain_dev_mounts
= plain_mounts
.get(dev
, [])
183 realpath_dev_mounts
= plain_mounts
.get(realpath_dev
, [])
185 plain_dev_real_mounts
= realpath_mounts
.get(dev
, [])
186 realpath_dev_real_mounts
= realpath_mounts
.get(realpath_dev
, [])
191 plain_dev_real_mounts
,
192 realpath_dev_real_mounts
195 for mounts
in mount_locations
:
196 if mounts
: # we have a matching mount
198 if destination
in mounts
:
200 '%s detected as mounted, exists at destination: %s', dev
, destination
204 logger
.info('%s was found as mounted')
206 logger
.info('%s was not found as mounted')
210 def get_mounts(devices
=False, paths
=False, realpath
=False):
212 Create a mapping of all available system mounts so that other helpers can
213 detect nicely what path or device is mounted
215 It ignores (most of) non existing devices, but since some setups might need
216 some extra device information, it will make an exception for:
221 If ``devices`` is set to ``True`` the mapping will be a device-to-path(s),
222 if ``paths`` is set to ``True`` then the mapping will be
225 :param realpath: Resolve devices to use their realpaths. This is useful for
226 paths like LVM where more than one path can point to the same device
230 do_not_skip
= ['tmpfs', 'devtmpfs']
231 default_to_devices
= devices
is False and paths
is False
233 with
open(PROCDIR
+ '/mounts', 'rb') as mounts
:
234 proc_mounts
= mounts
.readlines()
236 for line
in proc_mounts
:
237 fields
= [as_string(f
) for f
in line
.split()]
241 device
= os
.path
.realpath(fields
[0]) if fields
[0].startswith('/') else fields
[0]
244 path
= os
.path
.realpath(fields
[1])
245 # only care about actual existing devices
246 if not os
.path
.exists(device
) or not device
.startswith('/'):
247 if device
not in do_not_skip
:
249 if device
in devices_mounted
.keys():
250 devices_mounted
[device
].append(path
)
252 devices_mounted
[device
] = [path
]
253 if path
in paths_mounted
.keys():
254 paths_mounted
[path
].append(device
)
256 paths_mounted
[path
] = [device
]
258 # Default to returning information for devices if
259 if devices
is True or default_to_devices
:
260 return devices_mounted