Mini Shell
"""
Virtuozzo HA common functions
"""
import platform
from subprocess import CalledProcessError, check_output, Popen, PIPE
import sys
from rads.common import errprint
from rads.exceptions import HAError
def check_if_vz():
"Checks if Virtuozzo is in /etc/redhat-release"
return bool("Virtuozzo" in platform.linux_distribution()[0])
def get_os_maj_version():
"Returns major version of OS"
version = platform.linux_distribution()[1].split('.')[0]
return version
def check_vz7():
"""checks if havp in name and if platform is 7"""
return bool(check_if_vz() and get_os_maj_version() == "7")
def is_container_running(ctid):
"""returns True if the container is running on this HA node, False if it
isn't or if some other error occurs"""
prlctl_list_cmd = ['/usr/bin/prlctl', 'list', '-H', '-o', 'status', ctid]
try:
prlctl_list_run = Popen(prlctl_list_cmd, stdout=PIPE, stderr=PIPE)
except OSError:
errprint("OSError exception running \"prlctl list -H -o status %s\"" % ctid)
return False
prlctl_list_out, prlctl_list_err = prlctl_list_run.communicate()
if prlctl_list_run.returncode > 0:
return False
status = prlctl_list_out.split()[0]
return bool(str(status) == "running")
def get_name(ctid):
"""Obtain the name (aka legacy CTID) of a container. The input ctid
will be either a legacy CTID or a UUID depending whether we are on
VZ6 or VZ7"""
prlctl_list_cmd = ['/usr/bin/prlctl', 'list', '-H', '-o', 'name', ctid]
try:
prlctl_list_run = Popen(prlctl_list_cmd, stdout=PIPE, stderr=PIPE)
except OSError:
errprint("OSError exception running \"prlctl list -H -o name %s\"" % ctid)
return None
prlctl_list_out, prlctl_list_err = prlctl_list_run.communicate()
if prlctl_list_run.returncode > 0:
errprint("Error: \"prlctl list -H -o name %s\" returned %s\n\nSTDERR:\n\n%s" % (
ctid,
prlctl_list_run.returncode,
prlctl_list_err)
)
return None
name = prlctl_list_out.split()[0]
return str(name)
def get_envid(ctid):
"""Obtain the envid of a container. This determines what the subdirectory
of /vz/root and /vz/private will be. This also has to run on VZ4 which lacks
the envid field or prlctl, so we just return the CTID"""
try:
with open('/etc/virtuozzo-release', 'r') as file_ptr:
for line in file_ptr:
if line.startswith('Virtuozzo release 4'):
return str(ctid)
except IOError:
errprint("Error reading /etc/virtuozzo-release, is this a VZ server?")
return None
prlctl_list_cmd = ['/usr/bin/prlctl', 'list', '-H', '-o', 'envid', ctid]
try:
prlctl_list_run = Popen(prlctl_list_cmd, stdout=PIPE, stderr=PIPE)
except OSError:
errprint("OSError exception running \"prlctl list -H -o envid %s\"" % ctid)
return None
prlctl_list_out, prlctl_list_err = prlctl_list_run.communicate()
if prlctl_list_run.returncode > 0:
errprint("Error: \"prlctl list -H -o envid %s\" returned %s\n\nSTDERR:\n\n%s" % (
ctid,
prlctl_list_run.returncode,
prlctl_list_err)
)
return None
envid = prlctl_list_out.split()[0]
return str(envid)
def get_uuid(ctid):
"""Obtain the UUID of a container. Does not work on VZ4"""
prlctl_list_cmd = ['/usr/bin/prlctl', 'list', '-H', '-o', 'uuid', ctid]
try:
prlctl_list_run = Popen(prlctl_list_cmd, stdout=PIPE, stderr=PIPE)
except OSError:
errprint("OSError exception running \"prlctl list -H -o uuid %s\"" % ctid)
return None
prlctl_list_out, prlctl_list_err = prlctl_list_run.communicate()
if prlctl_list_run.returncode > 0:
errprint("Error: \"prlctl list -H -o uuid %s\" returned %s\n\nSTDERR:\n\n%s" % (
ctid,
prlctl_list_run.returncode,
prlctl_list_err)
)
return None
uuid = prlctl_list_out.split()[0]
uuid = uuid.strip("{}")
return str(uuid)
def _get_cts(*args, **kwargs):
"""Returns unparsed output of vzlist or prctl to list containers
kwargs is used (similar to sh) for sending special --flags
such as setting all=True"""
# so the returned dict will match the keys requested, store the original
# key in opts before mutating it to match what the subproc expects
if check_if_vz():
if not check_vz7() and 'ostemplate' in args:
# prlctl's ostemplate is broken and reports distro on vz6
# switch to vzlist; fix envid to veid if it was requested
cmd = ['/usr/sbin/vzlist', '-H']
opts = {x: 'veid' if x == 'envid' else x for x in args}
else:
# prctl refers to 'ctid' as 'name'
cmd = ['/usr/bin/prlctl', 'list', '-H']
opts = {x: 'name' if x == 'ctid' else x for x in args}
else: # OpenVZ
opts = {x: 'veid' if x == 'envid' else x for x in args}
cmd = ['/usr/sbin/vzlist', '-H']
for key, val in kwargs.iteritems():
if isinstance(val, basestring):
cmd.extend(['--{}'.format(key), val])
elif val is True:
cmd.append('--{}'.format(key))
# forces opts's vals to be in the same order as args
cmd_opts = ','.join([opts[x] for x in args])
cmd.extend(['-o', cmd_opts])
try:
stdout = check_output(cmd)
except CalledProcessError as fail:
raise HAError(str(fail))
return stdout
def get_cts(*args, **kwargs):
"""Returns containers according to platform as a list of dicts.
kwargs is used (similar to sh) for sending special --flags
such as setting all=True"""
if not args:
args = ['ctid']
stdout = _get_cts(*args, **kwargs)
ret = []
# process each line as a dict where keys are the arg and vals are the result
for row in stdout.splitlines():
row = row.strip()
if not row:
continue # blank line
row = row.split()
if len(row) != len(args):
raise HAError('unexpected columns: {!r}'.format(row))
ret.append({x: row[i] for i, x in enumerate(args)})
return ret
def list_cts(*args, **kwargs):
"""Prints containers according to platform.
kwargs is used (similar to sh) for sending special --flags
such as setting all=True"""
if not args:
args = ['ctid']
try:
list_output = _get_cts(*args, **kwargs)
if list_output:
for i in list_output.splitlines():
print i.strip()
except HAError as fail:
sys.exit(str(fail))
Zerion Mini Shell 1.0