summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Wolf <throughnothing@gmail.com>2011-08-11 15:49:58 -0400
committerWilliam Wolf <throughnothing@gmail.com>2011-08-11 15:49:58 -0400
commit5704f0a0cbc06c04a8ed6bf72bc1b5214016d083 (patch)
tree3bcee1f95393fce3273aa6618638fa6f4d3a986b
parent4275c9062e2d89c30472ba6646fd3c2503c0e984 (diff)
parentfe0bde67193ce76376e72a7263b89240a63722a8 (diff)
downloadnova-5704f0a0cbc06c04a8ed6bf72bc1b5214016d083.tar.gz
nova-5704f0a0cbc06c04a8ed6bf72bc1b5214016d083.tar.xz
nova-5704f0a0cbc06c04a8ed6bf72bc1b5214016d083.zip
merge from trunk
-rw-r--r--nova/console/xvp.py1
-rw-r--r--nova/flags.py3
-rw-r--r--nova/network/linux_net.py142
-rw-r--r--nova/tests/fake_utils.py8
-rw-r--r--nova/tests/test_libvirt.py10
-rw-r--r--nova/tests/test_volume.py10
-rw-r--r--nova/tests/test_xenapi.py10
-rw-r--r--nova/utils.py15
-rw-r--r--nova/virt/disk.py47
-rw-r--r--nova/virt/libvirt/connection.py14
-rw-r--r--nova/virt/libvirt/vif.py16
-rw-r--r--nova/virt/xenapi/vm_utils.py15
-rw-r--r--nova/virt/xenapi/vmops.py26
-rw-r--r--nova/virt/xenapi/volume_utils.py4
-rw-r--r--nova/volume/driver.py101
15 files changed, 216 insertions, 206 deletions
diff --git a/nova/console/xvp.py b/nova/console/xvp.py
index 3cd287183..2d6842044 100644
--- a/nova/console/xvp.py
+++ b/nova/console/xvp.py
@@ -20,7 +20,6 @@
import fcntl
import os
import signal
-import subprocess
from Cheetah import Template
diff --git a/nova/flags.py b/nova/flags.py
index eb6366ed9..7916501a4 100644
--- a/nova/flags.py
+++ b/nova/flags.py
@@ -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')
diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py
index 8ace07884..4e1e1f85a 100644
--- a/nova/network/linux_net.py
+++ b/nova/network/linux_net.py
@@ -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
diff --git a/nova/tests/fake_utils.py b/nova/tests/fake_utils.py
index be59970c9..84ab641ea 100644
--- a/nova/tests/fake_utils.py
+++ b/nova/tests/fake_utils.py
@@ -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)))
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index 17f1be967..2180cf4f0 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -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
diff --git a/nova/tests/test_volume.py b/nova/tests/test_volume.py
index c0f89601f..7888b6b0b 100644
--- a/nova/tests/test_volume.py
+++ b/nova/tests/test_volume.py
@@ -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()
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py
index 952277e3f..1deb5a780 100644
--- a/nova/tests/test_xenapi.py
+++ b/nova/tests/test_xenapi.py
@@ -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
diff --git a/nova/utils.py b/nova/utils.py
index 4b068e3a5..36374dbbb 100644
--- a/nova/utils.py
+++ b/nova/utils.py
@@ -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)
diff --git a/nova/virt/disk.py b/nova/virt/disk.py
index f8aea1f34..19f3ec185 100644
--- a/nova/virt/disk.py
+++ b/nova/virt/disk.py
@@ -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)
diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py
index 16efa7292..6d043577a 100644
--- a/nova/virt/libvirt/connection.py
+++ b/nova/virt/libvirt/connection.py
@@ -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'
diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py
index 711b05bae..e243d4fa0 100644
--- a/nova/virt/libvirt/vif.py
+++ b/nova/virt/libvirt/vif.py
@@ -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'])
diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py
index d20746076..6c44d53d4 100644
--- a/nova/virt/xenapi/vm_utils.py
+++ b/nova/virt/xenapi/vm_utils.py
@@ -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)
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 50aa0d3b2..b9cd59946 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -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)
diff --git a/nova/virt/xenapi/volume_utils.py b/nova/virt/xenapi/volume_utils.py
index 7821a4f7e..5d5eb824f 100644
--- a/nova/virt/xenapi/volume_utils.py
+++ b/nova/virt/xenapi/volume_utils.py
@@ -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:
diff --git a/nova/volume/driver.py b/nova/volume/driver.py
index 23e845deb..c99534c07 100644
--- a/nova/volume/driver.py
+++ b/nova/volume/driver.py
@@ -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