]>
git.proxmox.com Git - ceph.git/blob - ceph/src/ceph-volume/ceph_volume/util/system.py
8 from ceph_volume
import process
9 from . import as_string
11 logger
= logging
.getLogger(__name__
)
13 # TODO: get these out of here and into a common area for others to consume
14 if platform
.system() == 'FreeBSD':
16 DEFAULT_FS_TYPE
= 'zfs'
17 PROCDIR
= '/compat/linux/proc'
18 # FreeBSD does not have blockdevices any more
23 DEFAULT_FS_TYPE
= 'xfs'
25 BLOCKDIR
= '/sys/block'
30 return str(uuid
.uuid4())
33 def get_ceph_user_ids():
35 Return the id and gid of the ceph user
38 user
= pwd
.getpwnam('ceph')
40 # is this even possible?
41 raise RuntimeError('"ceph" user is not available in the current system')
42 return user
[2], user
[3]
45 def mkdir_p(path
, chown
=True):
47 A `mkdir -p` that defaults to chown the path to the ceph user
52 if e
.errno
== errno
.EEXIST
:
57 uid
, gid
= get_ceph_user_ids()
58 os
.chown(path
, uid
, gid
)
61 def chown(path
, recursive
=True):
63 ``chown`` a path to the ceph user (uid and guid fetched at runtime)
65 uid
, gid
= get_ceph_user_ids()
66 if os
.path
.islink(path
):
67 path
= os
.path
.realpath(path
)
69 process
.run(['chown', '-R', 'ceph:ceph', path
])
71 os
.chown(path
, uid
, gid
)
76 Detect if a file path is a binary or not. Will falsely report as binary
77 when utf-16 encoded. In the ceph universe there is no such risk (yet)
79 with
open(path
, 'rb') as fp
:
80 contents
= fp
.read(8192)
81 if b
'\x00' in contents
: # a null byte may signal binary
86 class tmp_mount(object):
88 Temporarily mount a device on a temporary directory,
89 and unmount it upon exit
91 When ``encrypted`` is set to ``True``, the exit method will call out to
92 close the device so that it doesn't remain open after mounting. It is
93 assumed that it will be open because otherwise it wouldn't be possible to
94 mount in the first place
97 def __init__(self
, device
, encrypted
=False):
100 self
.encrypted
= encrypted
103 self
.path
= tempfile
.mkdtemp()
112 def __exit__(self
, exc_type
, exc_val
, exc_tb
):
119 # avoid a circular import from the encryption module
120 from ceph_volume
.util
import encryption
121 encryption
.dmcrypt_close(self
.device
)
126 Removes mounts at the given path
135 def path_is_mounted(path
, destination
=None):
137 Check if the given path is mounted
139 mounts
= get_mounts(paths
=True)
140 realpath
= os
.path
.realpath(path
)
141 mounted_locations
= mounts
.get(realpath
, [])
144 return destination
in mounted_locations
145 return mounted_locations
!= []
148 def device_is_mounted(dev
, destination
=None):
150 Check if the given device is mounted, optionally validating that a
153 plain_mounts
= get_mounts(devices
=True)
154 realpath_mounts
= get_mounts(devices
=True, realpath
=True)
155 realpath_dev
= os
.path
.realpath(dev
) if dev
.startswith('/') else dev
156 destination
= os
.path
.realpath(destination
) if destination
else None
158 plain_dev_mounts
= plain_mounts
.get(dev
, [])
159 realpath_dev_mounts
= plain_mounts
.get(realpath_dev
, [])
161 plain_dev_real_mounts
= realpath_mounts
.get(dev
, [])
162 realpath_dev_real_mounts
= realpath_mounts
.get(realpath_dev
, [])
167 plain_dev_real_mounts
,
168 realpath_dev_real_mounts
171 for mounts
in mount_locations
:
172 if mounts
: # we have a matching mount
174 if destination
in mounts
:
176 '%s detected as mounted, exists at destination: %s', dev
, destination
180 logger
.info('%s was found as mounted')
182 logger
.info('%s was not found as mounted')
186 def get_mounts(devices
=False, paths
=False, realpath
=False):
188 Create a mapping of all available system mounts so that other helpers can
189 detect nicely what path or device is mounted
191 It ignores (most of) non existing devices, but since some setups might need
192 some extra device information, it will make an exception for:
197 If ``devices`` is set to ``True`` the mapping will be a device-to-path(s),
198 if ``paths`` is set to ``True`` then the mapping will be
201 :param realpath: Resolve devices to use their realpaths. This is useful for
202 paths like LVM where more than one path can point to the same device
206 do_not_skip
= ['tmpfs', 'devtmpfs']
207 default_to_devices
= devices
is False and paths
is False
209 with
open(PROCDIR
+ '/mounts', 'rb') as mounts
:
210 proc_mounts
= mounts
.readlines()
212 for line
in proc_mounts
:
213 fields
= [as_string(f
) for f
in line
.split()]
217 device
= os
.path
.realpath(fields
[0]) if fields
[0].startswith('/') else fields
[0]
220 path
= os
.path
.realpath(fields
[1])
221 # only care about actual existing devices
222 if not os
.path
.exists(device
) or not device
.startswith('/'):
223 if device
not in do_not_skip
:
225 if device
in devices_mounted
.keys():
226 devices_mounted
[device
].append(path
)
228 devices_mounted
[device
] = [path
]
229 if path
in paths_mounted
.keys():
230 paths_mounted
[path
].append(device
)
232 paths_mounted
[path
] = [device
]
234 # Default to returning information for devices if
235 if devices
is True or default_to_devices
:
236 return devices_mounted