* Removes rogue direct usage of subprocess module by proper utils.execute calls
* Adds a run_as_root parameter to utils.execute, that prefixes your command with FLAG.root_helper (which defaults to 'sudo') * Turns all sudo calls into run_as_root=True calls * Update fakes accordingly * Replaces usage of "sudo -E" and "addl_env" parameter into passing environment in the command (allows it to be compatible with alternative sudo_helpers) * Additionally, forces close_fds=True on all utils.execute calls, since it's a more secure default
This commit is contained in:
@@ -20,7 +20,6 @@
|
||||
import fcntl
|
||||
import os
|
||||
import signal
|
||||
import subprocess
|
||||
|
||||
from Cheetah import Template
|
||||
|
||||
|
||||
@@ -392,3 +392,6 @@ DEFINE_bool('start_guests_on_host_boot', False,
|
||||
'Whether to restart guests when the host reboots')
|
||||
DEFINE_bool('resume_guests_state_on_host_boot', False,
|
||||
'Whether to start guests, that was running before the host reboot')
|
||||
|
||||
DEFINE_string('root_helper', 'sudo',
|
||||
'Command prefix to use for running commands as root')
|
||||
|
||||
@@ -296,14 +296,14 @@ class IptablesManager(object):
|
||||
|
||||
for cmd, tables in s:
|
||||
for table in tables:
|
||||
current_table, _ = self.execute('sudo',
|
||||
'%s-save' % (cmd,),
|
||||
current_table, _ = self.execute('%s-save' % (cmd,),
|
||||
'-t', '%s' % (table,),
|
||||
run_as_root=True,
|
||||
attempts=5)
|
||||
current_lines = current_table.split('\n')
|
||||
new_filter = self._modify_rules(current_lines,
|
||||
tables[table])
|
||||
self.execute('sudo', '%s-restore' % (cmd,),
|
||||
self.execute('%s-restore' % (cmd,), run_as_root=True,
|
||||
process_input='\n'.join(new_filter),
|
||||
attempts=5)
|
||||
|
||||
@@ -396,21 +396,22 @@ def init_host():
|
||||
|
||||
def bind_floating_ip(floating_ip, check_exit_code=True):
|
||||
"""Bind ip to public interface."""
|
||||
_execute('sudo', 'ip', 'addr', 'add', floating_ip,
|
||||
_execute('ip', 'addr', 'add', floating_ip,
|
||||
'dev', FLAGS.public_interface,
|
||||
check_exit_code=check_exit_code)
|
||||
run_as_root=True, check_exit_code=check_exit_code)
|
||||
|
||||
|
||||
def unbind_floating_ip(floating_ip):
|
||||
"""Unbind a public ip from public interface."""
|
||||
_execute('sudo', 'ip', 'addr', 'del', floating_ip,
|
||||
'dev', FLAGS.public_interface)
|
||||
_execute('ip', 'addr', 'del', floating_ip,
|
||||
'dev', FLAGS.public_interface, run_as_root=True)
|
||||
|
||||
|
||||
def ensure_metadata_ip():
|
||||
"""Sets up local metadata ip."""
|
||||
_execute('sudo', 'ip', 'addr', 'add', '169.254.169.254/32',
|
||||
'scope', 'link', 'dev', 'lo', check_exit_code=False)
|
||||
_execute('ip', 'addr', 'add', '169.254.169.254/32',
|
||||
'scope', 'link', 'dev', 'lo',
|
||||
run_as_root=True, check_exit_code=False)
|
||||
|
||||
|
||||
def ensure_vlan_forward(public_ip, port, private_ip):
|
||||
@@ -464,9 +465,11 @@ def ensure_vlan(vlan_num, bridge_interface):
|
||||
interface = 'vlan%s' % vlan_num
|
||||
if not _device_exists(interface):
|
||||
LOG.debug(_('Starting VLAN inteface %s'), interface)
|
||||
_execute('sudo', 'vconfig', 'set_name_type', 'VLAN_PLUS_VID_NO_PAD')
|
||||
_execute('sudo', 'vconfig', 'add', bridge_interface, vlan_num)
|
||||
_execute('sudo', 'ip', 'link', 'set', interface, 'up')
|
||||
_execute('vconfig', 'set_name_type', 'VLAN_PLUS_VID_NO_PAD',
|
||||
run_as_root=True)
|
||||
_execute('vconfig', 'add', bridge_interface, vlan_num,
|
||||
run_as_root=True)
|
||||
_execute('ip', 'link', 'set', interface, 'up', run_as_root=True)
|
||||
return interface
|
||||
|
||||
|
||||
@@ -487,58 +490,62 @@ def ensure_bridge(bridge, interface, net_attrs=None):
|
||||
"""
|
||||
if not _device_exists(bridge):
|
||||
LOG.debug(_('Starting Bridge interface for %s'), interface)
|
||||
_execute('sudo', 'brctl', 'addbr', bridge)
|
||||
_execute('sudo', 'brctl', 'setfd', bridge, 0)
|
||||
# _execute('sudo brctl setageing %s 10' % bridge)
|
||||
_execute('sudo', 'brctl', 'stp', bridge, 'off')
|
||||
_execute('sudo', 'ip', 'link', 'set', bridge, 'up')
|
||||
_execute('brctl', 'addbr', bridge, run_as_root=True)
|
||||
_execute('brctl', 'setfd', bridge, 0, run_as_root=True)
|
||||
_execute('brctl', 'stp', bridge, 'off', run_as_root=True)
|
||||
_execute('ip', 'link', 'set', bridge, 'up', run_as_root=True)
|
||||
if net_attrs:
|
||||
# NOTE(vish): The ip for dnsmasq has to be the first address on the
|
||||
# bridge for it to respond to reqests properly
|
||||
suffix = net_attrs['cidr'].rpartition('/')[2]
|
||||
out, err = _execute('sudo', 'ip', 'addr', 'add',
|
||||
out, err = _execute('ip', 'addr', 'add',
|
||||
'%s/%s' %
|
||||
(net_attrs['dhcp_server'], suffix),
|
||||
'brd',
|
||||
net_attrs['broadcast'],
|
||||
'dev',
|
||||
bridge,
|
||||
run_as_root=True,
|
||||
check_exit_code=False)
|
||||
if err and err != 'RTNETLINK answers: File exists\n':
|
||||
raise exception.Error('Failed to add ip: %s' % err)
|
||||
if(FLAGS.use_ipv6):
|
||||
_execute('sudo', 'ip', '-f', 'inet6', 'addr',
|
||||
_execute('ip', '-f', 'inet6', 'addr',
|
||||
'change', net_attrs['cidr_v6'],
|
||||
'dev', bridge)
|
||||
'dev', bridge, run_as_root=True)
|
||||
# NOTE(vish): If the public interface is the same as the
|
||||
# bridge, then the bridge has to be in promiscuous
|
||||
# to forward packets properly.
|
||||
if(FLAGS.public_interface == bridge):
|
||||
_execute('sudo', 'ip', 'link', 'set',
|
||||
'dev', bridge, 'promisc', 'on')
|
||||
_execute('ip', 'link', 'set',
|
||||
'dev', bridge, 'promisc', 'on', run_as_root=True)
|
||||
if interface:
|
||||
# NOTE(vish): This will break if there is already an ip on the
|
||||
# interface, so we move any ips to the bridge
|
||||
gateway = None
|
||||
out, err = _execute('sudo', 'route', '-n')
|
||||
out, err = _execute('route', '-n', run_as_root=True)
|
||||
for line in out.split('\n'):
|
||||
fields = line.split()
|
||||
if fields and fields[0] == '0.0.0.0' and fields[-1] == interface:
|
||||
gateway = fields[1]
|
||||
_execute('sudo', 'route', 'del', 'default', 'gw', gateway,
|
||||
'dev', interface, check_exit_code=False)
|
||||
out, err = _execute('sudo', 'ip', 'addr', 'show', 'dev', interface,
|
||||
'scope', 'global')
|
||||
_execute('route', 'del', 'default', 'gw', gateway,
|
||||
'dev', interface,
|
||||
check_exit_code=False, run_as_root=True)
|
||||
out, err = _execute('ip', 'addr', 'show', 'dev', interface,
|
||||
'scope', 'global', run_as_root=True)
|
||||
for line in out.split('\n'):
|
||||
fields = line.split()
|
||||
if fields and fields[0] == 'inet':
|
||||
params = fields[1:-1]
|
||||
_execute(*_ip_bridge_cmd('del', params, fields[-1]))
|
||||
_execute(*_ip_bridge_cmd('add', params, bridge))
|
||||
_execute(*_ip_bridge_cmd('del', params, fields[-1]),
|
||||
run_as_root=True)
|
||||
_execute(*_ip_bridge_cmd('add', params, bridge),
|
||||
run_as_root=True)
|
||||
if gateway:
|
||||
_execute('sudo', 'route', 'add', 'default', 'gw', gateway)
|
||||
out, err = _execute('sudo', 'brctl', 'addif', bridge, interface,
|
||||
check_exit_code=False)
|
||||
_execute('route', 'add', 'default', 'gw', gateway,
|
||||
run_as_root=True)
|
||||
out, err = _execute('brctl', 'addif', bridge, interface,
|
||||
check_exit_code=False, run_as_root=True)
|
||||
|
||||
if (err and err != "device %s is already a member of a bridge; can't "
|
||||
"enslave it to bridge %s.\n" % (interface, bridge)):
|
||||
@@ -602,18 +609,33 @@ def update_dhcp(context, network_ref):
|
||||
check_exit_code=False)
|
||||
if conffile in out:
|
||||
try:
|
||||
_execute('sudo', 'kill', '-HUP', pid)
|
||||
_execute('kill', '-HUP', pid, run_as_root=True)
|
||||
return
|
||||
except Exception as exc: # pylint: disable=W0703
|
||||
LOG.debug(_('Hupping dnsmasq threw %s'), exc)
|
||||
else:
|
||||
LOG.debug(_('Pid %d is stale, relaunching dnsmasq'), pid)
|
||||
|
||||
# FLAGFILE and DNSMASQ_INTERFACE in env
|
||||
env = {'FLAGFILE': FLAGS.dhcpbridge_flagfile,
|
||||
'DNSMASQ_INTERFACE': network_ref['bridge']}
|
||||
command = _dnsmasq_cmd(network_ref)
|
||||
_execute(*command, addl_env=env)
|
||||
cmd = ['FLAGFILE=%s' % FLAGS.dhcpbridge_flagfile,
|
||||
'DNSMASQ_INTERFACE=%s' % network_ref['bridge'],
|
||||
'dnsmasq',
|
||||
'--strict-order',
|
||||
'--bind-interfaces',
|
||||
'--interface=%s' % network_ref['bridge'],
|
||||
'--conf-file=%s' % FLAGS.dnsmasq_config_file,
|
||||
'--domain=%s' % FLAGS.dhcp_domain,
|
||||
'--pid-file=%s' % _dhcp_file(network_ref['bridge'], 'pid'),
|
||||
'--listen-address=%s' % network_ref['dhcp_server'],
|
||||
'--except-interface=lo',
|
||||
'--dhcp-range=%s,static,120s' % network_ref['dhcp_start'],
|
||||
'--dhcp-lease-max=%s' % len(netaddr.IPNetwork(network_ref['cidr'])),
|
||||
'--dhcp-hostsfile=%s' % _dhcp_file(network_ref['bridge'], 'conf'),
|
||||
'--dhcp-script=%s' % FLAGS.dhcpbridge,
|
||||
'--leasefile-ro']
|
||||
if FLAGS.dns_server:
|
||||
cmd += ['-h', '-R', '--server=%s' % FLAGS.dns_server]
|
||||
|
||||
_execute(*cmd, run_as_root=True)
|
||||
|
||||
|
||||
@utils.synchronized('radvd_start')
|
||||
@@ -646,13 +668,17 @@ interface %s
|
||||
% pid, check_exit_code=False)
|
||||
if conffile in out:
|
||||
try:
|
||||
_execute('sudo', 'kill', pid)
|
||||
_execute('kill', pid, run_as_root=True)
|
||||
except Exception as exc: # pylint: disable=W0703
|
||||
LOG.debug(_('killing radvd threw %s'), exc)
|
||||
else:
|
||||
LOG.debug(_('Pid %d is stale, relaunching radvd'), pid)
|
||||
command = _ra_cmd(network_ref)
|
||||
_execute(*command)
|
||||
|
||||
cmd = ['radvd',
|
||||
'-C', '%s' % _ra_file(network_ref['bridge'], 'conf'),
|
||||
'-p', '%s' % _ra_file(network_ref['bridge'], 'pid')]
|
||||
|
||||
_execute(*cmd, run_as_root=True)
|
||||
|
||||
|
||||
def _host_lease(fixed_ip_ref):
|
||||
@@ -696,43 +722,13 @@ def _device_exists(device):
|
||||
return not err
|
||||
|
||||
|
||||
def _dnsmasq_cmd(net):
|
||||
"""Builds dnsmasq command."""
|
||||
cmd = ['sudo', '-E', 'dnsmasq',
|
||||
'--strict-order',
|
||||
'--bind-interfaces',
|
||||
'--interface=%s' % net['bridge'],
|
||||
'--conf-file=%s' % FLAGS.dnsmasq_config_file,
|
||||
'--domain=%s' % FLAGS.dhcp_domain,
|
||||
'--pid-file=%s' % _dhcp_file(net['bridge'], 'pid'),
|
||||
'--listen-address=%s' % net['dhcp_server'],
|
||||
'--except-interface=lo',
|
||||
'--dhcp-range=%s,static,120s' % net['dhcp_start'],
|
||||
'--dhcp-lease-max=%s' % len(netaddr.IPNetwork(net['cidr'])),
|
||||
'--dhcp-hostsfile=%s' % _dhcp_file(net['bridge'], 'conf'),
|
||||
'--dhcp-script=%s' % FLAGS.dhcpbridge,
|
||||
'--leasefile-ro']
|
||||
if FLAGS.dns_server:
|
||||
cmd += ['-h', '-R', '--server=%s' % FLAGS.dns_server]
|
||||
return cmd
|
||||
|
||||
|
||||
def _ra_cmd(net):
|
||||
"""Builds radvd command."""
|
||||
cmd = ['sudo', '-E', 'radvd',
|
||||
# '-u', 'nobody',
|
||||
'-C', '%s' % _ra_file(net['bridge'], 'conf'),
|
||||
'-p', '%s' % _ra_file(net['bridge'], 'pid')]
|
||||
return cmd
|
||||
|
||||
|
||||
def _stop_dnsmasq(network):
|
||||
"""Stops the dnsmasq instance for a given network."""
|
||||
pid = _dnsmasq_pid_for(network)
|
||||
|
||||
if pid:
|
||||
try:
|
||||
_execute('sudo', 'kill', '-TERM', pid)
|
||||
_execute('kill', '-TERM', pid, run_as_root=True)
|
||||
except Exception as exc: # pylint: disable=W0703
|
||||
LOG.debug(_('Killing dnsmasq threw %s'), exc)
|
||||
|
||||
@@ -788,7 +784,7 @@ def _ra_pid_for(bridge):
|
||||
|
||||
def _ip_bridge_cmd(action, params, device):
|
||||
"""Build commands to add/del ips to bridges/devices."""
|
||||
cmd = ['sudo', 'ip', 'addr', action]
|
||||
cmd = ['ip', 'addr', action]
|
||||
cmd.extend(params)
|
||||
cmd.extend(['dev', device])
|
||||
return cmd
|
||||
|
||||
@@ -64,8 +64,10 @@ def fake_execute(*cmd_parts, **kwargs):
|
||||
global _fake_execute_repliers
|
||||
|
||||
process_input = kwargs.get('process_input', None)
|
||||
addl_env = kwargs.get('addl_env', None)
|
||||
check_exit_code = kwargs.get('check_exit_code', 0)
|
||||
delay_on_retry = kwargs.get('delay_on_retry', True)
|
||||
attempts = kwargs.get('attempts', 1)
|
||||
run_as_root = kwargs.get('run_as_root', False)
|
||||
cmd_str = ' '.join(str(part) for part in cmd_parts)
|
||||
|
||||
LOG.debug(_("Faking execution of cmd (subprocess): %s"), cmd_str)
|
||||
@@ -87,7 +89,9 @@ def fake_execute(*cmd_parts, **kwargs):
|
||||
# Alternative is a function, so call it
|
||||
reply = reply_handler(cmd_parts,
|
||||
process_input=process_input,
|
||||
addl_env=addl_env,
|
||||
delay_on_retry=delay_on_retry,
|
||||
attempts=attempts,
|
||||
run_as_root=run_as_root,
|
||||
check_exit_code=check_exit_code)
|
||||
except exception.ProcessExecutionError as e:
|
||||
LOG.debug(_('Faked command raised an exception %s' % str(e)))
|
||||
|
||||
@@ -921,18 +921,18 @@ class IptablesFirewallTestCase(test.TestCase):
|
||||
# self.fw.add_instance(instance_ref)
|
||||
def fake_iptables_execute(*cmd, **kwargs):
|
||||
process_input = kwargs.get('process_input', None)
|
||||
if cmd == ('sudo', 'ip6tables-save', '-t', 'filter'):
|
||||
if cmd == ('ip6tables-save', '-t', 'filter'):
|
||||
return '\n'.join(self.in6_filter_rules), None
|
||||
if cmd == ('sudo', 'iptables-save', '-t', 'filter'):
|
||||
if cmd == ('iptables-save', '-t', 'filter'):
|
||||
return '\n'.join(self.in_filter_rules), None
|
||||
if cmd == ('sudo', 'iptables-save', '-t', 'nat'):
|
||||
if cmd == ('iptables-save', '-t', 'nat'):
|
||||
return '\n'.join(self.in_nat_rules), None
|
||||
if cmd == ('sudo', 'iptables-restore'):
|
||||
if cmd == ('iptables-restore',):
|
||||
lines = process_input.split('\n')
|
||||
if '*filter' in lines:
|
||||
self.out_rules = lines
|
||||
return '', ''
|
||||
if cmd == ('sudo', 'ip6tables-restore'):
|
||||
if cmd == ('ip6tables-restore',):
|
||||
lines = process_input.split('\n')
|
||||
if '*filter' in lines:
|
||||
self.out6_rules = lines
|
||||
|
||||
@@ -414,8 +414,9 @@ class ISCSITestCase(DriverTestCase):
|
||||
self.mox.StubOutWithMock(self.volume.driver, '_execute')
|
||||
for i in volume_id_list:
|
||||
tid = db.volume_get_iscsi_target_num(self.context, i)
|
||||
self.volume.driver._execute("sudo", "ietadm", "--op", "show",
|
||||
"--tid=%(tid)d" % locals())
|
||||
self.volume.driver._execute("ietadm", "--op", "show",
|
||||
"--tid=%(tid)d" % locals(),
|
||||
run_as_root=True)
|
||||
|
||||
self.stream.truncate(0)
|
||||
self.mox.ReplayAll()
|
||||
@@ -433,8 +434,9 @@ class ISCSITestCase(DriverTestCase):
|
||||
# the first vblade process isn't running
|
||||
tid = db.volume_get_iscsi_target_num(self.context, volume_id_list[0])
|
||||
self.mox.StubOutWithMock(self.volume.driver, '_execute')
|
||||
self.volume.driver._execute("sudo", "ietadm", "--op", "show",
|
||||
"--tid=%(tid)d" % locals()).AndRaise(
|
||||
self.volume.driver._execute("ietadm", "--op", "show",
|
||||
"--tid=%(tid)d" % locals(),
|
||||
run_as_root=True).AndRaise(
|
||||
exception.ProcessExecutionError())
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
@@ -548,8 +548,8 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
return '', ''
|
||||
|
||||
fake_utils.fake_execute_set_repliers([
|
||||
# Capture the sudo tee .../etc/network/interfaces command
|
||||
(r'(sudo\s+)?tee.*interfaces', _tee_handler),
|
||||
# Capture the tee .../etc/network/interfaces command
|
||||
(r'tee.*interfaces', _tee_handler),
|
||||
])
|
||||
self._test_spawn(glance_stubs.FakeGlance.IMAGE_MACHINE,
|
||||
glance_stubs.FakeGlance.IMAGE_KERNEL,
|
||||
@@ -592,9 +592,9 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
return '', ''
|
||||
|
||||
fake_utils.fake_execute_set_repliers([
|
||||
(r'(sudo\s+)?mount', _mount_handler),
|
||||
(r'(sudo\s+)?umount', _umount_handler),
|
||||
(r'(sudo\s+)?tee.*interfaces', _tee_handler)])
|
||||
(r'mount', _mount_handler),
|
||||
(r'umount', _umount_handler),
|
||||
(r'tee.*interfaces', _tee_handler)])
|
||||
self._test_spawn(1, 2, 3, check_injection=True)
|
||||
|
||||
# tee must not run in this case, where an injection-capable
|
||||
|
||||
@@ -28,6 +28,7 @@ import netaddr
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import shlex
|
||||
import socket
|
||||
import struct
|
||||
import sys
|
||||
@@ -131,40 +132,42 @@ def execute(*cmd, **kwargs):
|
||||
|
||||
:cmd Passed to subprocess.Popen.
|
||||
:process_input Send to opened process.
|
||||
:addl_env Added to the processes env.
|
||||
:check_exit_code Defaults to 0. Raise exception.ProcessExecutionError
|
||||
unless program exits with this code.
|
||||
:delay_on_retry True | False. Defaults to True. If set to True, wait a
|
||||
short amount of time before retrying.
|
||||
:attempts How many times to retry cmd.
|
||||
:run_as_root True | False. Defaults to False. If set to True,
|
||||
the command is prefixed by the command specified
|
||||
in the root_helper FLAG.
|
||||
|
||||
:raises exception.Error on receiving unknown arguments
|
||||
:raises exception.ProcessExecutionError
|
||||
"""
|
||||
|
||||
process_input = kwargs.pop('process_input', None)
|
||||
addl_env = kwargs.pop('addl_env', None)
|
||||
check_exit_code = kwargs.pop('check_exit_code', 0)
|
||||
delay_on_retry = kwargs.pop('delay_on_retry', True)
|
||||
attempts = kwargs.pop('attempts', 1)
|
||||
run_as_root = kwargs.pop('run_as_root', False)
|
||||
if len(kwargs):
|
||||
raise exception.Error(_('Got unknown keyword args '
|
||||
'to utils.execute: %r') % kwargs)
|
||||
|
||||
if run_as_root:
|
||||
cmd = shlex.split(FLAGS.root_helper) + list(cmd)
|
||||
cmd = map(str, cmd)
|
||||
|
||||
while attempts > 0:
|
||||
attempts -= 1
|
||||
try:
|
||||
LOG.debug(_('Running cmd (subprocess): %s'), ' '.join(cmd))
|
||||
env = os.environ.copy()
|
||||
if addl_env:
|
||||
env.update(addl_env)
|
||||
_PIPE = subprocess.PIPE # pylint: disable=E1101
|
||||
obj = subprocess.Popen(cmd,
|
||||
stdin=_PIPE,
|
||||
stdout=_PIPE,
|
||||
stderr=_PIPE,
|
||||
env=env)
|
||||
close_fds=True)
|
||||
result = None
|
||||
if process_input is not None:
|
||||
result = obj.communicate(process_input)
|
||||
|
||||
@@ -73,7 +73,7 @@ def inject_data(image, key=None, net=None, partition=None, nbd=False):
|
||||
try:
|
||||
if not partition is None:
|
||||
# create partition
|
||||
out, err = utils.execute('sudo', 'kpartx', '-a', device)
|
||||
out, err = utils.execute('kpartx', '-a', device, run_as_root=True)
|
||||
if err:
|
||||
raise exception.Error(_('Failed to load partition: %s') % err)
|
||||
mapped_device = '/dev/mapper/%sp%s' % (device.split('/')[-1],
|
||||
@@ -90,14 +90,14 @@ def inject_data(image, key=None, net=None, partition=None, nbd=False):
|
||||
mapped_device)
|
||||
|
||||
# Configure ext2fs so that it doesn't auto-check every N boots
|
||||
out, err = utils.execute('sudo', 'tune2fs',
|
||||
'-c', 0, '-i', 0, mapped_device)
|
||||
out, err = utils.execute('tune2fs', '-c', 0, '-i', 0,
|
||||
mapped_device, run_as_root=True)
|
||||
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
try:
|
||||
# mount loopback to dir
|
||||
out, err = utils.execute(
|
||||
'sudo', 'mount', mapped_device, tmpdir)
|
||||
out, err = utils.execute('mount', mapped_device, tmpdir,
|
||||
run_as_root=True)
|
||||
if err:
|
||||
raise exception.Error(_('Failed to mount filesystem: %s')
|
||||
% err)
|
||||
@@ -106,14 +106,14 @@ def inject_data(image, key=None, net=None, partition=None, nbd=False):
|
||||
inject_data_into_fs(tmpdir, key, net, utils.execute)
|
||||
finally:
|
||||
# unmount device
|
||||
utils.execute('sudo', 'umount', mapped_device)
|
||||
utils.execute('umount', mapped_device, run_as_root=True)
|
||||
finally:
|
||||
# remove temporary directory
|
||||
utils.execute('rmdir', tmpdir)
|
||||
finally:
|
||||
if not partition is None:
|
||||
# remove partitions
|
||||
utils.execute('sudo', 'kpartx', '-d', device)
|
||||
utils.execute('kpartx', '-d', device, run_as_root=True)
|
||||
finally:
|
||||
_unlink_device(device, nbd)
|
||||
|
||||
@@ -128,7 +128,7 @@ def setup_container(image, container_dir=None, nbd=False):
|
||||
"""
|
||||
try:
|
||||
device = _link_device(image, nbd)
|
||||
utils.execute('sudo', 'mount', device, container_dir)
|
||||
utils.execute('mount', device, container_dir, run_as_root=True)
|
||||
except Exception, exn:
|
||||
LOG.exception(_('Failed to mount filesystem: %s'), exn)
|
||||
_unlink_device(device, nbd)
|
||||
@@ -144,9 +144,9 @@ def destroy_container(target, instance, nbd=False):
|
||||
"""
|
||||
try:
|
||||
container_dir = '%s/rootfs' % target
|
||||
utils.execute('sudo', 'umount', container_dir)
|
||||
utils.execute('umount', container_dir, run_as_root=True)
|
||||
finally:
|
||||
out, err = utils.execute('sudo', 'losetup', '-a')
|
||||
out, err = utils.execute('losetup', '-a', run_as_root=True)
|
||||
for loop in out.splitlines():
|
||||
if instance['name'] in loop:
|
||||
device = loop.split(loop, ':')
|
||||
@@ -157,7 +157,7 @@ def _link_device(image, nbd):
|
||||
"""Link image to device using loopback or nbd"""
|
||||
if nbd:
|
||||
device = _allocate_device()
|
||||
utils.execute('sudo', 'qemu-nbd', '-c', device, image)
|
||||
utils.execute('qemu-nbd', '-c', device, image, run_as_root=True)
|
||||
# NOTE(vish): this forks into another process, so give it a chance
|
||||
# to set up before continuuing
|
||||
for i in xrange(FLAGS.timeout_nbd):
|
||||
@@ -166,7 +166,8 @@ def _link_device(image, nbd):
|
||||
time.sleep(1)
|
||||
raise exception.Error(_('nbd device %s did not show up') % device)
|
||||
else:
|
||||
out, err = utils.execute('sudo', 'losetup', '--find', '--show', image)
|
||||
out, err = utils.execute('losetup', '--find', '--show', image,
|
||||
run_as_root=True)
|
||||
if err:
|
||||
raise exception.Error(_('Could not attach image to loopback: %s')
|
||||
% err)
|
||||
@@ -176,10 +177,10 @@ def _link_device(image, nbd):
|
||||
def _unlink_device(device, nbd):
|
||||
"""Unlink image from device using loopback or nbd"""
|
||||
if nbd:
|
||||
utils.execute('sudo', 'qemu-nbd', '-d', device)
|
||||
utils.execute('qemu-nbd', '-d', device, run_as_root=True)
|
||||
_free_device(device)
|
||||
else:
|
||||
utils.execute('sudo', 'losetup', '--detach', device)
|
||||
utils.execute('losetup', '--detach', device, run_as_root=True)
|
||||
|
||||
|
||||
_DEVICES = ['/dev/nbd%s' % i for i in xrange(FLAGS.max_nbd_devices)]
|
||||
@@ -220,12 +221,12 @@ def _inject_key_into_fs(key, fs, execute=None):
|
||||
fs is the path to the base of the filesystem into which to inject the key.
|
||||
"""
|
||||
sshdir = os.path.join(fs, 'root', '.ssh')
|
||||
utils.execute('sudo', 'mkdir', '-p', sshdir) # existing dir doesn't matter
|
||||
utils.execute('sudo', 'chown', 'root', sshdir)
|
||||
utils.execute('sudo', 'chmod', '700', sshdir)
|
||||
utils.execute('mkdir', '-p', sshdir, run_as_root=True)
|
||||
utils.execute('chown', 'root', sshdir, run_as_root=True)
|
||||
utils.execute('chmod', '700', sshdir, run_as_root=True)
|
||||
keyfile = os.path.join(sshdir, 'authorized_keys')
|
||||
utils.execute('sudo', 'tee', '-a', keyfile,
|
||||
process_input='\n' + key.strip() + '\n')
|
||||
utils.execute('tee', '-a', keyfile,
|
||||
process_input='\n' + key.strip() + '\n', run_as_root=True)
|
||||
|
||||
|
||||
def _inject_net_into_fs(net, fs, execute=None):
|
||||
@@ -234,8 +235,8 @@ def _inject_net_into_fs(net, fs, execute=None):
|
||||
net is the contents of /etc/network/interfaces.
|
||||
"""
|
||||
netdir = os.path.join(os.path.join(fs, 'etc'), 'network')
|
||||
utils.execute('sudo', 'mkdir', '-p', netdir) # existing dir doesn't matter
|
||||
utils.execute('sudo', 'chown', 'root:root', netdir)
|
||||
utils.execute('sudo', 'chmod', 755, netdir)
|
||||
utils.execute('mkdir', '-p', netdir, run_as_root=True)
|
||||
utils.execute('chown', 'root:root', netdir, run_as_root=True)
|
||||
utils.execute('chmod', 755, netdir, run_as_root=True)
|
||||
netfile = os.path.join(netdir, 'interfaces')
|
||||
utils.execute('sudo', 'tee', netfile, process_input=net)
|
||||
utils.execute('tee', netfile, process_input=net, run_as_root=True)
|
||||
|
||||
@@ -43,7 +43,6 @@ import os
|
||||
import random
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
@@ -612,9 +611,10 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
|
||||
if virsh_output.startswith('/dev/'):
|
||||
LOG.info(_("cool, it's a device"))
|
||||
out, err = utils.execute('sudo', 'dd',
|
||||
out, err = utils.execute('dd',
|
||||
"if=%s" % virsh_output,
|
||||
'iflag=nonblock',
|
||||
run_as_root=True,
|
||||
check_exit_code=False)
|
||||
return out
|
||||
else:
|
||||
@@ -637,7 +637,7 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
console_log = os.path.join(FLAGS.instances_path, instance['name'],
|
||||
'console.log')
|
||||
|
||||
utils.execute('sudo', 'chown', os.getuid(), console_log)
|
||||
utils.execute('chown', os.getuid(), console_log, run_as_root=True)
|
||||
|
||||
if FLAGS.libvirt_type == 'xen':
|
||||
# Xen is special
|
||||
@@ -685,10 +685,10 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
ajaxterm_cmd = 'sudo socat - %s' \
|
||||
% get_pty_for_instance(instance['name'])
|
||||
|
||||
cmd = '%s/tools/ajaxterm/ajaxterm.py --command "%s" -t %s -p %s' \
|
||||
% (utils.novadir(), ajaxterm_cmd, token, port)
|
||||
cmd = ['%s/tools/ajaxterm/ajaxterm.py' % utils.novadir(),
|
||||
'--command', ajaxterm_cmd, '-t', token, '-p', port]
|
||||
|
||||
subprocess.Popen(cmd, shell=True)
|
||||
utils.execute(cmd)
|
||||
return {'token': token, 'host': host, 'port': port}
|
||||
|
||||
def get_host_ip_addr(self):
|
||||
@@ -947,7 +947,7 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
' data into image %(img_id)s (%(e)s)') % locals())
|
||||
|
||||
if FLAGS.libvirt_type == 'uml':
|
||||
utils.execute('sudo', 'chown', 'root', basepath('disk'))
|
||||
utils.execute('chown', 'root', basepath('disk'), run_as_root=True)
|
||||
|
||||
if FLAGS.libvirt_type == 'uml':
|
||||
_disk_prefix = 'ubd'
|
||||
|
||||
@@ -103,16 +103,18 @@ class LibvirtOpenVswitchDriver(VIFDriver):
|
||||
dev = "tap-%s" % vif_id
|
||||
iface_id = "nova-" + vif_id
|
||||
if not linux_net._device_exists(dev):
|
||||
utils.execute('sudo', 'ip', 'tuntap', 'add', dev, 'mode', 'tap')
|
||||
utils.execute('sudo', 'ip', 'link', 'set', dev, 'up')
|
||||
utils.execute('sudo', 'ovs-vsctl', '--', '--may-exist', 'add-port',
|
||||
utils.execute('ip', 'tuntap', 'add', dev, 'mode', 'tap',
|
||||
run_as_root=True)
|
||||
utils.execute('ip', 'link', 'set', dev, 'up', run_as_root=True)
|
||||
utils.execute('ovs-vsctl', '--', '--may-exist', 'add-port',
|
||||
FLAGS.libvirt_ovs_bridge, dev,
|
||||
'--', 'set', 'Interface', dev,
|
||||
"external-ids:iface-id=%s" % iface_id,
|
||||
'--', 'set', 'Interface', dev,
|
||||
"external-ids:iface-status=active",
|
||||
'--', 'set', 'Interface', dev,
|
||||
"external-ids:attached-mac=%s" % mapping['mac'])
|
||||
"external-ids:attached-mac=%s" % mapping['mac'],
|
||||
run_as_root=True)
|
||||
|
||||
result = {
|
||||
'script': '',
|
||||
@@ -126,9 +128,9 @@ class LibvirtOpenVswitchDriver(VIFDriver):
|
||||
vif_id = str(instance['id']) + "-" + str(network['id'])
|
||||
dev = "tap-%s" % vif_id
|
||||
try:
|
||||
utils.execute('sudo', 'ovs-vsctl', 'del-port',
|
||||
network['bridge'], dev)
|
||||
utils.execute('sudo', 'ip', 'link', 'delete', dev)
|
||||
utils.execute('ovs-vsctl', 'del-port',
|
||||
network['bridge'], dev, run_as_root=True)
|
||||
utils.execute('ip', 'link', 'delete', dev, run_as_root=True)
|
||||
except exception.ProcessExecutionError:
|
||||
LOG.warning(_("Failed while unplugging vif of instance '%s'"),
|
||||
instance['name'])
|
||||
|
||||
@@ -967,7 +967,7 @@ def _stream_disk(dev, image_type, virtual_size, image_file):
|
||||
offset = MBR_SIZE_BYTES
|
||||
_write_partition(virtual_size, dev)
|
||||
|
||||
utils.execute('sudo', 'chown', os.getuid(), '/dev/%s' % dev)
|
||||
utils.execute('chown', os.getuid(), '/dev/%s' % dev, run_as_root=True)
|
||||
|
||||
with open('/dev/%s' % dev, 'wb') as f:
|
||||
f.seek(offset)
|
||||
@@ -986,10 +986,11 @@ def _write_partition(virtual_size, dev):
|
||||
def execute(*cmd, **kwargs):
|
||||
return utils.execute(*cmd, **kwargs)
|
||||
|
||||
execute('sudo', 'parted', '--script', dest, 'mklabel', 'msdos')
|
||||
execute('sudo', 'parted', '--script', dest, 'mkpart', 'primary',
|
||||
execute('parted', '--script', dest, 'mklabel', 'msdos', run_as_root=True)
|
||||
execute('parted', '--script', dest, 'mkpart', 'primary',
|
||||
'%ds' % primary_first,
|
||||
'%ds' % primary_last)
|
||||
'%ds' % primary_last,
|
||||
run_as_root=True)
|
||||
|
||||
LOG.debug(_('Writing partition table %s done.'), dest)
|
||||
|
||||
@@ -1002,9 +1003,9 @@ def get_name_label_for_image(image):
|
||||
def _mount_filesystem(dev_path, dir):
|
||||
"""mounts the device specified by dev_path in dir"""
|
||||
try:
|
||||
out, err = utils.execute('sudo', 'mount',
|
||||
out, err = utils.execute('mount',
|
||||
'-t', 'ext2,ext3',
|
||||
dev_path, dir)
|
||||
dev_path, dir, run_as_root=True)
|
||||
except exception.ProcessExecutionError as e:
|
||||
err = str(e)
|
||||
return err
|
||||
@@ -1056,7 +1057,7 @@ def _mounted_processing(device, key, net):
|
||||
disk.inject_data_into_fs(tmpdir, key, net,
|
||||
utils.execute)
|
||||
finally:
|
||||
utils.execute('sudo', 'umount', dev_path)
|
||||
utils.execute('umount', dev_path, run_as_root=True)
|
||||
else:
|
||||
LOG.info(_('Failed to mount filesystem (expected for '
|
||||
'non-linux instances): %s') % err)
|
||||
|
||||
@@ -1334,12 +1334,6 @@ class VMOps(object):
|
||||
########################################################################
|
||||
|
||||
|
||||
def _runproc(cmd):
|
||||
pipe = subprocess.PIPE
|
||||
return subprocess.Popen([cmd], shell=True, stdin=pipe, stdout=pipe,
|
||||
stderr=pipe, close_fds=True)
|
||||
|
||||
|
||||
class SimpleDH(object):
|
||||
"""
|
||||
This class wraps all the functionality needed to implement
|
||||
@@ -1396,22 +1390,18 @@ class SimpleDH(object):
|
||||
mpi = M2Crypto.m2.bn_to_mpi(bn)
|
||||
return mpi
|
||||
|
||||
def _run_ssl(self, text, extra_args=None):
|
||||
if not extra_args:
|
||||
extra_args = ''
|
||||
cmd = 'enc -aes-128-cbc -A -a -pass pass:%s -nosalt %s' % (
|
||||
self._shared, extra_args)
|
||||
proc = _runproc('openssl %s' % cmd)
|
||||
proc.stdin.write(text)
|
||||
proc.stdin.close()
|
||||
proc.wait()
|
||||
err = proc.stderr.read()
|
||||
def _run_ssl(self, text, decrypt=False):
|
||||
cmd = ['openssl', 'aes-128-cbc', '-A', '-a', '-pass',
|
||||
'pass:%s' % self._shared, '-nosalt']
|
||||
if decrypt:
|
||||
cmd.append('-d')
|
||||
out, err = utils.execute(*cmd, process_input=text)
|
||||
if err:
|
||||
raise RuntimeError(_('OpenSSL error: %s') % err)
|
||||
return proc.stdout.read()
|
||||
return out
|
||||
|
||||
def encrypt(self, text):
|
||||
return self._run_ssl(text).strip('\n')
|
||||
|
||||
def decrypt(self, text):
|
||||
return self._run_ssl(text, '-d')
|
||||
return self._run_ssl(text, decrypt=True)
|
||||
|
||||
@@ -252,10 +252,10 @@ def _get_target(volume_id):
|
||||
volume_id)
|
||||
result = (None, None)
|
||||
try:
|
||||
(r, _e) = utils.execute('sudo', 'iscsiadm',
|
||||
(r, _e) = utils.execute('iscsiadm',
|
||||
'-m', 'discovery',
|
||||
'-t', 'sendtargets',
|
||||
'-p', volume_ref['host'])
|
||||
'-p', volume_ref['host'], run_as_root=True)
|
||||
except exception.ProcessExecutionError, exc:
|
||||
LOG.exception(exc)
|
||||
else:
|
||||
|
||||
@@ -65,14 +65,14 @@ class VolumeDriver(object):
|
||||
self._execute = execute
|
||||
self._sync_exec = sync_exec
|
||||
|
||||
def _try_execute(self, *command):
|
||||
def _try_execute(self, *command, **kwargs):
|
||||
# NOTE(vish): Volume commands can partially fail due to timing, but
|
||||
# running them a second time on failure will usually
|
||||
# recover nicely.
|
||||
tries = 0
|
||||
while True:
|
||||
try:
|
||||
self._execute(*command)
|
||||
self._execute(*command, **kwargs)
|
||||
return True
|
||||
except exception.ProcessExecutionError:
|
||||
tries = tries + 1
|
||||
@@ -84,24 +84,26 @@ class VolumeDriver(object):
|
||||
|
||||
def check_for_setup_error(self):
|
||||
"""Returns an error if prerequisites aren't met"""
|
||||
out, err = self._execute('sudo', 'vgs', '--noheadings', '-o', 'name')
|
||||
out, err = self._execute('vgs', '--noheadings', '-o', 'name',
|
||||
run_as_root=True)
|
||||
volume_groups = out.split()
|
||||
if not FLAGS.volume_group in volume_groups:
|
||||
raise exception.Error(_("volume group %s doesn't exist")
|
||||
% FLAGS.volume_group)
|
||||
|
||||
def _create_volume(self, volume_name, sizestr):
|
||||
self._try_execute('sudo', 'lvcreate', '-L', sizestr, '-n',
|
||||
volume_name, FLAGS.volume_group)
|
||||
self._try_execute('lvcreate', '-L', sizestr, '-n',
|
||||
volume_name, FLAGS.volume_group, run_as_root=True)
|
||||
|
||||
def _copy_volume(self, srcstr, deststr, size_in_g):
|
||||
self._execute('sudo', 'dd', 'if=%s' % srcstr, 'of=%s' % deststr,
|
||||
'count=%d' % (size_in_g * 1024), 'bs=1M')
|
||||
self._execute('dd', 'if=%s' % srcstr, 'of=%s' % deststr,
|
||||
'count=%d' % (size_in_g * 1024), 'bs=1M',
|
||||
run_as_root=True)
|
||||
|
||||
def _volume_not_present(self, volume_name):
|
||||
path_name = '%s/%s' % (FLAGS.volume_group, volume_name)
|
||||
try:
|
||||
self._try_execute('sudo', 'lvdisplay', path_name)
|
||||
self._try_execute('lvdisplay', path_name, run_as_root=True)
|
||||
except Exception as e:
|
||||
# If the volume isn't present
|
||||
return True
|
||||
@@ -112,9 +114,10 @@ class VolumeDriver(object):
|
||||
# zero out old volumes to prevent data leaking between users
|
||||
# TODO(ja): reclaiming space should be done lazy and low priority
|
||||
self._copy_volume('/dev/zero', self.local_path(volume), size_in_g)
|
||||
self._try_execute('sudo', 'lvremove', '-f', "%s/%s" %
|
||||
self._try_execute('lvremove', '-f', "%s/%s" %
|
||||
(FLAGS.volume_group,
|
||||
self._escape_snapshot(volume['name'])))
|
||||
self._escape_snapshot(volume['name'])),
|
||||
run_as_root=True)
|
||||
|
||||
def _sizestr(self, size_in_g):
|
||||
if int(size_in_g) == 0:
|
||||
@@ -147,10 +150,11 @@ class VolumeDriver(object):
|
||||
|
||||
# TODO(yamahata): lvm can't delete origin volume only without
|
||||
# deleting derived snapshots. Can we do something fancy?
|
||||
out, err = self._execute('sudo', 'lvdisplay', '--noheading',
|
||||
out, err = self._execute('lvdisplay', '--noheading',
|
||||
'-C', '-o', 'Attr',
|
||||
'%s/%s' % (FLAGS.volume_group,
|
||||
volume['name']))
|
||||
volume['name']),
|
||||
run_as_root=True)
|
||||
# fake_execute returns None resulting unit test error
|
||||
if out:
|
||||
out = out.strip()
|
||||
@@ -162,10 +166,10 @@ class VolumeDriver(object):
|
||||
def create_snapshot(self, snapshot):
|
||||
"""Creates a snapshot."""
|
||||
orig_lv_name = "%s/%s" % (FLAGS.volume_group, snapshot['volume_name'])
|
||||
self._try_execute('sudo', 'lvcreate', '-L',
|
||||
self._try_execute('lvcreate', '-L',
|
||||
self._sizestr(snapshot['volume_size']),
|
||||
'--name', self._escape_snapshot(snapshot['name']),
|
||||
'--snapshot', orig_lv_name)
|
||||
'--snapshot', orig_lv_name, run_as_root=True)
|
||||
|
||||
def delete_snapshot(self, snapshot):
|
||||
"""Deletes a snapshot."""
|
||||
@@ -233,13 +237,14 @@ class AOEDriver(VolumeDriver):
|
||||
blade_id) = self.db.volume_allocate_shelf_and_blade(context,
|
||||
volume['id'])
|
||||
self._try_execute(
|
||||
'sudo', 'vblade-persist', 'setup',
|
||||
'vblade-persist', 'setup',
|
||||
shelf_id,
|
||||
blade_id,
|
||||
FLAGS.aoe_eth_dev,
|
||||
"/dev/%s/%s" %
|
||||
(FLAGS.volume_group,
|
||||
volume['name']))
|
||||
volume['name']),
|
||||
run_as_root=True)
|
||||
# NOTE(vish): The standard _try_execute does not work here
|
||||
# because these methods throw errors if other
|
||||
# volumes on this host are in the process of
|
||||
@@ -248,28 +253,29 @@ class AOEDriver(VolumeDriver):
|
||||
# just wait a bit for the current volume to
|
||||
# be ready and ignore any errors.
|
||||
time.sleep(2)
|
||||
self._execute('sudo', 'vblade-persist', 'auto', 'all',
|
||||
check_exit_code=False)
|
||||
self._execute('sudo', 'vblade-persist', 'start', 'all',
|
||||
check_exit_code=False)
|
||||
self._execute('vblade-persist', 'auto', 'all',
|
||||
check_exit_code=False, run_as_root=True)
|
||||
self._execute('vblade-persist', 'start', 'all',
|
||||
check_exit_code=False, run_as_root=True)
|
||||
|
||||
def remove_export(self, context, volume):
|
||||
"""Removes an export for a logical volume."""
|
||||
(shelf_id,
|
||||
blade_id) = self.db.volume_get_shelf_and_blade(context,
|
||||
volume['id'])
|
||||
self._try_execute('sudo', 'vblade-persist', 'stop',
|
||||
shelf_id, blade_id)
|
||||
self._try_execute('sudo', 'vblade-persist', 'destroy',
|
||||
shelf_id, blade_id)
|
||||
self._try_execute('vblade-persist', 'stop',
|
||||
shelf_id, blade_id, run_as_root=True)
|
||||
self._try_execute('vblade-persist', 'destroy',
|
||||
shelf_id, blade_id, run_as_root=True)
|
||||
|
||||
def discover_volume(self, context, _volume):
|
||||
"""Discover volume on a remote host."""
|
||||
(shelf_id,
|
||||
blade_id) = self.db.volume_get_shelf_and_blade(context,
|
||||
_volume['id'])
|
||||
self._execute('sudo', 'aoe-discover')
|
||||
out, err = self._execute('sudo', 'aoe-stat', check_exit_code=False)
|
||||
self._execute('aoe-discover', run_as_root=True)
|
||||
out, err = self._execute('aoe-stat', check_exit_code=False,
|
||||
run_as_root=True)
|
||||
device_path = 'e%(shelf_id)d.%(blade_id)d' % locals()
|
||||
if out.find(device_path) >= 0:
|
||||
return "/dev/etherd/%s" % device_path
|
||||
@@ -285,8 +291,8 @@ class AOEDriver(VolumeDriver):
|
||||
(shelf_id,
|
||||
blade_id) = self.db.volume_get_shelf_and_blade(context,
|
||||
volume_id)
|
||||
cmd = ('sudo', 'vblade-persist', 'ls', '--no-header')
|
||||
out, _err = self._execute(*cmd)
|
||||
cmd = ('vblade-persist', 'ls', '--no-header')
|
||||
out, _err = self._execute(*cmd, run_as_root=True)
|
||||
exported = False
|
||||
for line in out.split('\n'):
|
||||
param = line.split(' ')
|
||||
@@ -348,16 +354,18 @@ class ISCSIDriver(VolumeDriver):
|
||||
|
||||
iscsi_name = "%s%s" % (FLAGS.iscsi_target_prefix, volume['name'])
|
||||
volume_path = "/dev/%s/%s" % (FLAGS.volume_group, volume['name'])
|
||||
self._sync_exec('sudo', 'ietadm', '--op', 'new',
|
||||
self._sync_exec('ietadm', '--op', 'new',
|
||||
"--tid=%s" % iscsi_target,
|
||||
'--params',
|
||||
"Name=%s" % iscsi_name,
|
||||
run_as_root=True,
|
||||
check_exit_code=False)
|
||||
self._sync_exec('sudo', 'ietadm', '--op', 'new',
|
||||
self._sync_exec('ietadm', '--op', 'new',
|
||||
"--tid=%s" % iscsi_target,
|
||||
'--lun=0',
|
||||
'--params',
|
||||
"Path=%s,Type=fileio" % volume_path,
|
||||
run_as_root=True,
|
||||
check_exit_code=False)
|
||||
|
||||
def _ensure_iscsi_targets(self, context, host):
|
||||
@@ -378,13 +386,13 @@ class ISCSIDriver(VolumeDriver):
|
||||
volume['host'])
|
||||
iscsi_name = "%s%s" % (FLAGS.iscsi_target_prefix, volume['name'])
|
||||
volume_path = "/dev/%s/%s" % (FLAGS.volume_group, volume['name'])
|
||||
self._execute('sudo', 'ietadm', '--op', 'new',
|
||||
self._execute('ietadm', '--op', 'new',
|
||||
'--tid=%s' % iscsi_target,
|
||||
'--params', 'Name=%s' % iscsi_name)
|
||||
self._execute('sudo', 'ietadm', '--op', 'new',
|
||||
'--params', 'Name=%s' % iscsi_name, run_as_root=True)
|
||||
self._execute('ietadm', '--op', 'new',
|
||||
'--tid=%s' % iscsi_target,
|
||||
'--lun=0', '--params',
|
||||
'Path=%s,Type=fileio' % volume_path)
|
||||
'Path=%s,Type=fileio' % volume_path, run_as_root=True)
|
||||
|
||||
def remove_export(self, context, volume):
|
||||
"""Removes an export for a logical volume."""
|
||||
@@ -399,18 +407,18 @@ class ISCSIDriver(VolumeDriver):
|
||||
try:
|
||||
# ietadm show will exit with an error
|
||||
# this export has already been removed
|
||||
self._execute('sudo', 'ietadm', '--op', 'show',
|
||||
'--tid=%s' % iscsi_target)
|
||||
self._execute('ietadm', '--op', 'show',
|
||||
'--tid=%s' % iscsi_target, run_as_root=True)
|
||||
except Exception as e:
|
||||
LOG.info(_("Skipping remove_export. No iscsi_target " +
|
||||
"is presently exported for volume: %d"), volume['id'])
|
||||
return
|
||||
|
||||
self._execute('sudo', 'ietadm', '--op', 'delete',
|
||||
self._execute('ietadm', '--op', 'delete',
|
||||
'--tid=%s' % iscsi_target,
|
||||
'--lun=0')
|
||||
self._execute('sudo', 'ietadm', '--op', 'delete',
|
||||
'--tid=%s' % iscsi_target)
|
||||
'--lun=0', run_as_root=True)
|
||||
self._execute('ietadm', '--op', 'delete',
|
||||
'--tid=%s' % iscsi_target, run_as_root=True)
|
||||
|
||||
def _do_iscsi_discovery(self, volume):
|
||||
#TODO(justinsb): Deprecate discovery and use stored info
|
||||
@@ -419,8 +427,9 @@ class ISCSIDriver(VolumeDriver):
|
||||
|
||||
volume_name = volume['name']
|
||||
|
||||
(out, _err) = self._execute('sudo', 'iscsiadm', '-m', 'discovery',
|
||||
'-t', 'sendtargets', '-p', volume['host'])
|
||||
(out, _err) = self._execute('iscsiadm', '-m', 'discovery',
|
||||
'-t', 'sendtargets', '-p', volume['host'],
|
||||
run_as_root=True)
|
||||
for target in out.splitlines():
|
||||
if FLAGS.iscsi_ip_prefix in target and volume_name in target:
|
||||
return target
|
||||
@@ -483,10 +492,10 @@ class ISCSIDriver(VolumeDriver):
|
||||
return properties
|
||||
|
||||
def _run_iscsiadm(self, iscsi_properties, iscsi_command):
|
||||
(out, err) = self._execute('sudo', 'iscsiadm', '-m', 'node', '-T',
|
||||
(out, err) = self._execute('iscsiadm', '-m', 'node', '-T',
|
||||
iscsi_properties['target_iqn'],
|
||||
'-p', iscsi_properties['target_portal'],
|
||||
iscsi_command)
|
||||
iscsi_command, run_as_root=True)
|
||||
LOG.debug("iscsiadm %s: stdout=%s stderr=%s" %
|
||||
(iscsi_command, out, err))
|
||||
return (out, err)
|
||||
@@ -560,8 +569,8 @@ class ISCSIDriver(VolumeDriver):
|
||||
|
||||
tid = self.db.volume_get_iscsi_target_num(context, volume_id)
|
||||
try:
|
||||
self._execute('sudo', 'ietadm', '--op', 'show',
|
||||
'--tid=%(tid)d' % locals())
|
||||
self._execute('ietadm', '--op', 'show',
|
||||
'--tid=%(tid)d' % locals(), run_as_root=True)
|
||||
except exception.ProcessExecutionError, e:
|
||||
# Instances remount read-only in this case.
|
||||
# /etc/init.d/iscsitarget restart and rebooting nova-volume
|
||||
|
||||
Reference in New Issue
Block a user