Move localloop to exec_sudo
One call in localloop requires the output of the command, so modify exec_sudo to buffer up output and return it. This is modelled on the same thing in package-installs-v2 which seems to work. Rather than return a subprocess exception, return a dib exception which everything should have imported anyway. The overall reason for this is to make our external calls more consistent for mocking in unit testing. Change-Id: I10d23b873dee9f775daef2a4c8be5671d02c386e
This commit is contained in:
parent
f5736f3178
commit
a1a549548a
@ -14,12 +14,12 @@
|
||||
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from diskimage_builder.block_device.exception import \
|
||||
BlockDeviceSetupException
|
||||
from diskimage_builder.block_device.plugin import NodeBase
|
||||
from diskimage_builder.block_device.plugin import PluginBase
|
||||
from diskimage_builder.block_device.utils import exec_sudo
|
||||
from diskimage_builder.block_device.utils import parse_abs_size_spec
|
||||
|
||||
|
||||
@ -41,17 +41,11 @@ def image_delete(filename):
|
||||
def loopdev_attach(filename):
|
||||
logger.info("loopdev attach")
|
||||
logger.debug("Calling [sudo losetup --show -f %s]", filename)
|
||||
subp = subprocess.Popen(["sudo", "losetup", "--show", "-f",
|
||||
filename], stdout=subprocess.PIPE)
|
||||
rval = subp.wait()
|
||||
if rval == 0:
|
||||
# [:-1]: Cut of the newline
|
||||
block_device = subp.stdout.read()[:-1].decode("utf-8")
|
||||
logger.info("New block device [%s]", block_device)
|
||||
return block_device
|
||||
else:
|
||||
logger.error("losetup failed")
|
||||
raise BlockDeviceSetupException("losetup failed")
|
||||
block_device = exec_sudo(["losetup", "--show", "-f", filename])
|
||||
# [:-1]: Cut of the newline
|
||||
block_device = block_device[:-1]
|
||||
logger.info("New block device [%s]", block_device)
|
||||
return block_device
|
||||
|
||||
|
||||
def loopdev_detach(loopdev):
|
||||
@ -59,19 +53,16 @@ def loopdev_detach(loopdev):
|
||||
# loopback dev may be tied up a bit by udev events triggered
|
||||
# by partition events
|
||||
for try_cnt in range(10, 1, -1):
|
||||
logger.debug("Calling [sudo losetup -d %s]", loopdev)
|
||||
subp = subprocess.Popen(["sudo", "losetup", "-d",
|
||||
loopdev])
|
||||
rval = subp.wait()
|
||||
if rval == 0:
|
||||
logger.info("Successfully detached [%s]", loopdev)
|
||||
return 0
|
||||
else:
|
||||
logger.error("loopdev detach failed")
|
||||
try:
|
||||
exec_sudo(["losetup", "-d", loopdev])
|
||||
return
|
||||
except BlockDeviceSetupException as e:
|
||||
# Do not raise an error - maybe other cleanup methods
|
||||
# can at least do some more work.
|
||||
logger.error("loopdev detach failed (%s)", e.returncode)
|
||||
|
||||
logger.debug("Gave up trying to detach [%s]", loopdev)
|
||||
return rval
|
||||
return 1
|
||||
|
||||
|
||||
class LocalLoopNode(NodeBase):
|
||||
|
@ -13,7 +13,6 @@
|
||||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
import subprocess
|
||||
|
||||
from diskimage_builder.block_device.exception \
|
||||
import BlockDeviceSetupException
|
||||
@ -313,8 +312,8 @@ class LVMUmountNode(NodeBase):
|
||||
def umount(self):
|
||||
try:
|
||||
exec_sudo(['pvscan', '--cache'])
|
||||
except subprocess.CalledProcessError as cpe:
|
||||
logger.debug("pvscan call result [%s]", cpe)
|
||||
except BlockDeviceSetupException as e:
|
||||
logger.info("pvscan call failed [%s]", e.returncode)
|
||||
|
||||
def get_edges(self):
|
||||
# This node depends on all physical device(s), which is
|
||||
|
@ -12,10 +12,14 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import locale
|
||||
import logging
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
from diskimage_builder.block_device.exception import \
|
||||
BlockDeviceSetupException
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -95,10 +99,16 @@ def exec_sudo(cmd):
|
||||
at debug levels.
|
||||
|
||||
Arguments:
|
||||
:param cmd: str command list; for Popen()
|
||||
:return: nothing
|
||||
:raises: subprocess.CalledProcessError if return code != 0
|
||||
|
||||
:param cmd: str command list; for Popen()
|
||||
:return: the stdout+stderror of the called command
|
||||
:raises BlockDeviceSetupException: if return code != 0.
|
||||
|
||||
Exception values similar to ``subprocess.CalledProcessError``
|
||||
|
||||
* ``returncode`` : returncode of child
|
||||
* ``cmd`` : the command run
|
||||
* ``output`` : stdout+stderr output
|
||||
"""
|
||||
assert isinstance(cmd, list)
|
||||
sudo_cmd = ["sudo"]
|
||||
@ -116,10 +126,20 @@ def exec_sudo(cmd):
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
|
||||
for line in iter(proc.stdout.readline, b""):
|
||||
logger.debug("exec_sudo: %s", line.rstrip())
|
||||
|
||||
out = ""
|
||||
with proc.stdout:
|
||||
for line in iter(proc.stdout.readline, b''):
|
||||
line = line.decode(encoding=locale.getpreferredencoding(False),
|
||||
errors='backslashreplace')
|
||||
out += line
|
||||
logger.debug("exec_sudo: %s", line.rstrip())
|
||||
proc.wait()
|
||||
if proc.returncode != 0:
|
||||
raise subprocess.CalledProcessError(proc.returncode,
|
||||
' '.join(sudo_cmd))
|
||||
|
||||
if proc.returncode:
|
||||
e = BlockDeviceSetupException("exec_sudo failed")
|
||||
e.returncode = proc.returncode
|
||||
e.cmd = ' '.join(sudo_cmd)
|
||||
e.output = out
|
||||
raise e
|
||||
|
||||
return out
|
||||
|
Loading…
Reference in New Issue
Block a user