Files
anvil/devstack/Shell.py
2012-01-17 10:27:54 -08:00

225 lines
5.7 KiB
Python

# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import getpass
import json
import os
import os.path
import shlex
import shutil
import subprocess
import sys
from Exceptions import (ProcessExecutionError, FileException)
import Logger
from Environment import (get_environment_bool, get_environment)
ROOT_HELPER = ["sudo"]
MKPW_CMD = ["openssl", 'rand', '-hex']
LOG = Logger.getLogger("install.shell")
def execute(*cmd, **kwargs):
process_input = kwargs.pop('process_input', None)
check_exit_code = kwargs.pop('check_exit_code', [0])
cwd = kwargs.pop('cwd', None)
env_overrides = kwargs.pop('env_overrides', None)
ignore_exit_code = False
if(isinstance(check_exit_code, bool)):
ignore_exit_code = not check_exit_code
check_exit_code = [0]
elif(isinstance(check_exit_code, int)):
check_exit_code = [check_exit_code]
run_as_root = kwargs.pop('run_as_root', False)
shell = kwargs.pop('shell', False)
if run_as_root:
cmd = ROOT_HELPER + list(cmd)
cmd = map(str, cmd)
if(shell):
cmd = " ".join(cmd)
LOG.debug('Running shell cmd: [%s]' % (cmd))
else:
LOG.debug('Running cmd: [%s]' % (' '.join(cmd)))
if(process_input != None):
LOG.debug('With stdin: %s' % (process_input))
stdin_fh = subprocess.PIPE
stdout_fh = subprocess.PIPE
stderr_fh = subprocess.PIPE
close_file_descriptors = True
if('stdout_fh' in kwargs.keys()):
stdout_fh = kwargs.get('stdout_fh')
LOG.debug("Redirecting stdout to file handle: %s" % (stdout_fh))
if('stdin_fh' in kwargs.keys()):
stdin_fh = kwargs.get('stdin_fh')
LOG.debug("Redirecting stdin to file handle: %s" % (stdin_fh))
if('stderr_fh' in kwargs.keys()):
stderr_fh = kwargs.get('stderr_fh')
LOG.debug("Redirecting stderr to file handle: %s" % (stderr_fh))
process_env = get_environment()
LOG.debug("With environment: %s" % (process_env))
if(env_overrides and len(env_overrides)):
LOG.debug("With additional environment overrides: %s" % (env_overrides))
for (k, v) in env_overrides.items():
process_env[k] = str(v)
obj = subprocess.Popen(cmd,
stdin=stdin_fh,
stdout=stdout_fh,
stderr=stderr_fh,
close_fds=close_file_descriptors,
cwd=cwd,
shell=shell,
env=process_env)
result = None
if(process_input != None):
result = obj.communicate(str(process_input))
else:
result = obj.communicate()
obj.stdin.close()
_returncode = obj.returncode
LOG.debug('Cmd result had return code: %s' % _returncode)
if((not ignore_exit_code) and (_returncode not in check_exit_code)):
(stdout, stderr) = result
ecmd = cmd
if(not shell):
ecmd = ' '.join(cmd)
raise ProcessExecutionError(
exit_code=_returncode,
stdout=stdout,
stderr=stderr,
cmd=ecmd)
else:
return result
def isfile(fn):
return os.path.isfile(fn)
def joinpths(*pths):
return os.path.join(*pths)
def password(prompt=None, genlen=8):
rd = ""
pass_ask = get_environment_bool("PASS_ASK", True)
if(pass_ask):
if(prompt):
rd = getpass.getpass(prompt)
else:
rd = getpass.getpass()
if(len(rd) == 0):
LOG.debug("Generating you a password of length: %s" % (genlen))
cmd = MKPW_CMD + [genlen]
(stdout, stderr) = execute(*cmd)
return stdout.strip()
else:
return rd
def mkdirslist(pth):
dirsmade = list()
if(os.path.isdir(pth)):
return dirsmade
dirspossible = set()
dirspossible.add(pth)
while(True):
splitup = os.path.split(pth)
pth = splitup[0]
base = splitup[1]
dirspossible.add(pth)
if(len(base) == 0):
break
dirstobe = list(dirspossible)
for pth in sorted(dirstobe):
if(not os.path.isdir(pth)):
os.mkdir(pth)
dirsmade.append(pth)
return dirsmade
def append_file(fn, text, flush=True):
with open(fn, "a") as f:
f.write(text)
if(flush):
f.flush()
def write_file(fn, text, flush=True):
with open(fn, "w") as f:
f.write(text)
if(flush):
f.flush()
def touch_file(fn, diethere=True):
if(not os.path.exists(fn)):
with open(fn, "w") as f:
f.truncate(0)
else:
if(diethere):
msg = "Can not touch file %s since it already exists" % (fn)
raise FileException(msg)
def load_file(fn):
data = ""
with open(fn, "r") as f:
data = f.read()
return data
def mkdir(pth, recurse=True):
if(not os.path.isdir(pth)):
if(recurse):
os.makedirs(pth)
else:
os.mkdir(pth)
def deldir(pth, force=True):
if(os.path.isdir(pth)):
if(force):
shutil.rmtree(pth)
else:
os.removedirs(pth)
def prompt(prompt):
rd = raw_input(prompt)
return rd
def unlink(pth, ignore=True):
try:
os.unlink(pth)
except OSError as (errono, emsg):
if(not ignore):
raise