if self.tags.get(key):
current_value = self.tags[key]
tag = "%s=%s" % (key, current_value)
- process.call(['pvchange', '--deltag', tag, self.pv_name])
+ process.call(['pvchange', '--deltag', tag, self.pv_name], run_on_host=True)
process.call(
[
'pvchange',
'--addtag', '%s=%s' % (key, value), self.pv_name
- ]
+ ],
+ run_on_host=True
)
'-f', # force it
'--yes', # answer yes to any prompts
device
- ])
+ ], run_on_host=True)
def remove_pv(pv_name):
'-f', # force it
pv_name
],
+ run_on_host=True,
fail_msg=fail_msg,
)
args = ['pvs', '--noheadings', '--readonly', '--separator=";"', '-S',
filters, '-o', fields]
- stdout, stderr, returncode = process.call(args, verbose_on_failure=False)
+ stdout, stderr, returncode = process.call(args, run_on_host=True, verbose_on_failure=False)
pvs_report = _output_parser(stdout, fields)
return [PVolume(**pv_report) for pv_report in pvs_report]
'vgcreate',
'--force',
'--yes',
- name] + devices
+ name] + devices,
+ run_on_host=True
)
return get_single_vg(filters={'vg_name': name})
'vgextend',
'--force',
'--yes',
- vg.name] + devices
+ vg.name] + devices,
+ run_on_host=True
)
return get_single_vg(filters={'vg_name': vg.name})
'vgreduce',
'--force',
'--yes',
- vg.name] + devices
+ vg.name] + devices,
+ run_on_host=True
)
return get_single_vg(filter={'vg_name': vg.name})
'-f', # force it
vg_name
],
+ run_on_host=True,
fail_msg=fail_msg,
)
filters = make_filters_lvmcmd_ready(filters, tags)
args = ['vgs'] + VG_CMD_OPTIONS + ['-S', filters, '-o', fields]
- stdout, stderr, returncode = process.call(args, verbose_on_failure=False)
+ stdout, stderr, returncode = process.call(args, run_on_host=True, verbose_on_failure=False)
vgs_report =_output_parser(stdout, fields)
return [VolumeGroup(**vg_report) for vg_report in vgs_report]
def get_device_vgs(device, name_prefix=''):
stdout, stderr, returncode = process.call(
['pvs'] + VG_CMD_OPTIONS + ['-o', VG_FIELDS, device],
+ run_on_host=True,
verbose_on_failure=False
)
vgs = _output_parser(stdout, VG_FIELDS)
return
del_tag_args = self._format_tag_args('--deltag', del_tags)
# --deltag returns successful even if the to be deleted tag is not set
- process.call(['lvchange'] + del_tag_args + [self.lv_path])
+ process.call(['lvchange'] + del_tag_args + [self.lv_path], run_on_host=True)
for k in del_tags.keys():
del self.tags[k]
"""
self.clear_tags(tags.keys())
add_tag_args = self._format_tag_args('--addtag', tags)
- process.call(['lvchange'] + add_tag_args + [self.lv_path])
+ process.call(['lvchange'] + add_tag_args + [self.lv_path], run_on_host=True)
for k, v in tags.items():
self.tags[k] = v
if self.tags.get(key):
current_value = self.tags[key]
tag = "%s=%s" % (key, current_value)
- process.call(['lvchange', '--deltag', tag, self.lv_path])
+ process.call(['lvchange', '--deltag', tag, self.lv_path], run_on_host=True)
del self.tags[key]
[
'lvchange',
'--addtag', '%s=%s' % (key, value), self.lv_path
- ]
+ ],
+ run_on_host=True
)
self.tags[key] = value
"""
Deactivate the LV by calling lvchange -an
"""
- process.call(['lvchange', '-an', self.lv_path])
+ process.call(['lvchange', '-an', self.lv_path], run_on_host=True)
def create_lv(name_prefix,
'100%FREE',
'-n', name, vg.vg_name
]
- process.run(command)
+ process.run(command, run_on_host=True)
lv = get_single_lv(filters={'lv_name': name, 'vg_name': vg.vg_name})
'-f', # force it
path
],
+ run_on_host=True,
show_command=True,
terminal_verbose=True,
)
filters = make_filters_lvmcmd_ready(filters, tags)
args = ['lvs'] + LV_CMD_OPTIONS + ['-S', filters, '-o', fields]
- stdout, stderr, returncode = process.call(args, verbose_on_failure=False)
+ stdout, stderr, returncode = process.call(args, run_on_host=True, verbose_on_failure=False)
lvs_report = _output_parser(stdout, fields)
return [Volume(**lv_report) for lv_report in lvs_report]
stdout, stderr, returncode = process.call(
['lvs', '--noheadings', '-o', LV_FIELDS, '-S',
'lv_name={}'.format(name)],
+ run_on_host=True,
verbose_on_failure=False
)
lvs = _output_parser(stdout, LV_FIELDS)
stdout, stderr, returncode = process.call(
['lvs', '--noheadings', '--separator=";"', '-a', '-o', LV_FIELDS, '-S',
'lv_tags={{{}}}'.format(lv_tag)],
+ run_on_host=True,
verbose_on_failure=False
)
lvs = _output_parser(stdout, LV_FIELDS)
def get_device_lvs(device, name_prefix=''):
stdout, stderr, returncode = process.call(
['pvs'] + LV_CMD_OPTIONS + ['-o', LV_FIELDS, device],
+ run_on_host=True,
verbose_on_failure=False
)
lvs = _output_parser(stdout, LV_FIELDS)
from fcntl import fcntl, F_GETFL, F_SETFL
-from os import O_NONBLOCK, read
+from os import O_NONBLOCK, read, path
import subprocess
from select import select
from ceph_volume import terminal
import logging
logger = logging.getLogger(__name__)
-
+host_rootfs = '/rootfs'
+run_host_cmd = [
+ 'nsenter',
+ '--root={}'.format(host_rootfs),
+ '--mount={}/proc/1/ns/mnt'.format(host_rootfs),
+ '--ipc={}/proc/1/ns/ipc'.format(host_rootfs),
+ '--net={}/proc/1/ns/net'.format(host_rootfs),
+ '--uts={}/proc/1/ns/uts'.format(host_rootfs)
+]
def which(executable):
"""
return "Running command: %s" % ' '.join(command)
-def run(command, **kw):
+def run(command, run_on_host=False, **kw):
"""
A real-time-logging implementation of a remote subprocess.Popen call where
a command is just executed on the remote end and no other handling is done.
"""
executable = which(command.pop(0))
command.insert(0, executable)
+ if run_on_host and path.isdir(host_rootfs):
+ command = run_host_cmd + command
stop_on_error = kw.pop('stop_on_error', True)
command_msg = obfuscate(command, kw.pop('obfuscate', None))
fail_msg = kw.pop('fail_msg', None)
logger.warning(msg)
-def call(command, **kw):
+def call(command, run_on_host=False, **kw):
"""
Similar to ``subprocess.Popen`` with the following changes:
"""
executable = which(command.pop(0))
command.insert(0, executable)
+ if run_on_host and path.isdir(host_rootfs):
+ command = run_host_cmd + command
terminal_verbose = kw.pop('terminal_verbose', False)
logfile_verbose = kw.pop('logfile_verbose', True)
verbose_on_failure = kw.pop('verbose_on_failure', True)
def test_uses_size(self, m_get_single_lv, m_call, m_run, monkeypatch):
m_get_single_lv.return_value = self.foo_volume
api.create_lv('foo', 0, vg=self.foo_group, size=419430400, tags={'ceph.type': 'data'})
- expected = ['lvcreate', '--yes', '-l', '100', '-n', 'foo-0', 'foo_group']
- m_run.assert_called_with(expected)
+ expected = (['lvcreate', '--yes', '-l', '100', '-n', 'foo-0', 'foo_group'])
+ m_run.assert_called_with(expected, run_on_host=True)
@patch('ceph_volume.api.lvm.process.run')
@patch('ceph_volume.api.lvm.process.call')
# 423624704 should be just under 1% off of the available size 419430400
api.create_lv('foo', 0, vg=foo_group, size=4232052736, tags={'ceph.type': 'data'})
expected = ['lvcreate', '--yes', '-l', '1000', '-n', 'foo-0', 'foo_group']
- m_run.assert_called_with(expected)
+ m_run.assert_called_with(expected, run_on_host=True)
@patch('ceph_volume.api.lvm.process.run')
@patch('ceph_volume.api.lvm.process.call')
m_get_single_lv.return_value = self.foo_volume
api.create_lv('foo', 0, vg=self.foo_group, extents='50', tags={'ceph.type': 'data'})
expected = ['lvcreate', '--yes', '-l', '50', '-n', 'foo-0', 'foo_group']
- m_run.assert_called_with(expected)
+ m_run.assert_called_with(expected, run_on_host=True)
@pytest.mark.parametrize("test_input,expected",
[(2, 50),
m_get_single_lv.return_value = self.foo_volume
api.create_lv('foo', 0, vg=self.foo_group, slots=test_input, tags={'ceph.type': 'data'})
expected = ['lvcreate', '--yes', '-l', str(expected), '-n', 'foo-0', 'foo_group']
- m_run.assert_called_with(expected)
+ m_run.assert_called_with(expected, run_on_host=True)
@patch('ceph_volume.api.lvm.process.run')
@patch('ceph_volume.api.lvm.process.call')
m_get_single_lv.return_value = self.foo_volume
api.create_lv('foo', 0, vg=self.foo_group, tags={'ceph.type': 'data'})
expected = ['lvcreate', '--yes', '-l', '100%FREE', '-n', 'foo-0', 'foo_group']
- m_run.assert_called_with(expected)
+ m_run.assert_called_with(expected, run_on_host=True)
@patch('ceph_volume.api.lvm.process.run')
@patch('ceph_volume.api.lvm.process.call')