Michael Basnight c8a5bc39dc Update oslo codebase within reddwarf.
* Updated logging,cfg,setup to new oslo
* Split out the paste ini from the conf files
* Modified reddwarf-api/server to use new modules
* Modified reddwarf-manage to use new cfg
* Added rpc helper for rpc services
* Modified reddwarf-taskmanager to use rpc helper
* Modified reddwarf-guestagent to use new rpc helper
* Fixed guestagent api to use rpc proxy
* Fixed taskmanager module to conform to new rpc
* Updated guestagent manager/pkg to use new rpc
* Updated api paste to use keystoneclient auth_token
* Updated managers to use periodic tasks

Implements: blueprint reddwarf/upgrade-oslo

Change-Id: I9ad1b441eca855a4304454014ae746ec51bef8f3
2012-12-18 21:18:28 -06:00

230 lines
7.6 KiB
Python

# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2011 OpenStack, LLC.
# All Rights Reserved.
#
# 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.
"""
Manages packages on the Guest VM.
"""
import commands
import pexpect
import re
from reddwarf.common import exception
from reddwarf.common import utils
from reddwarf.common.exception import ProcessExecutionError
from reddwarf.openstack.common import log as logging
from reddwarf.openstack.common.gettextutils import _
LOG = logging.getLogger(__name__)
class PkgAdminLockError(exception.ReddwarfError):
pass
class PkgPermissionError(exception.ReddwarfError):
pass
class PkgPackageStateError(exception.ReddwarfError):
pass
class PkgNotFoundError(exception.NotFound):
pass
class PkgTimeout(exception.ReddwarfError):
pass
OK = 0
RUN_DPKG_FIRST = 1
REINSTALL_FIRST = 2
def kill_proc(child):
child.delayafterclose = 1
child.delayafterterminate = 1
child.close(force=True)
def wait_and_close_proc(child, time_out=-1):
child.expect(pexpect.EOF, timeout=time_out)
child.close()
def _fix(time_out):
"""Sometimes you have to run this command before a pkg will install."""
#sudo dpkg --configure -a
child = pexpect.spawn("sudo -E dpkg --configure -a")
wait_and_close_proc(child, time_out)
def _install(package_name, time_out):
"""Attempts to install a package.
Returns OK if the package installs fine or a result code if a
recoverable-error occurred.
Raises an exception if a non-recoverable error or time out occurs.
"""
child = pexpect.spawn("sudo -E DEBIAN_FRONTEND=noninteractive "
"apt-get -y --allow-unauthenticated install %s"
% package_name)
try:
i = child.expect(['.*password*',
'E: Unable to locate package %s' % package_name,
"Couldn't find package % s" % package_name,
("dpkg was interrupted, you must manually run "
"'sudo dpkg --configure -a'"),
"Unable to lock the administration directory",
"Setting up %s*" % package_name,
"is already the newest version"],
timeout=time_out)
if i == 0:
raise PkgPermissionError("Invalid permissions.")
elif i == 1 or i == 2:
raise PkgNotFoundError("Could not find apt %s" % package_name)
elif i == 3:
return RUN_DPKG_FIRST
elif i == 4:
raise PkgAdminLockError()
except pexpect.TIMEOUT:
kill_proc(child)
raise PkgTimeout("Process timeout after %i seconds." % time_out)
try:
wait_and_close_proc(child)
except pexpect.TIMEOUT as e:
LOG.error("wait_and_close_proc failed: %s" % e)
#TODO(tim.simpson): As of RDL, and on my machine exclusively (in
# both Virtual Box and VmWare!) this fails, but
# the package is installed.
return OK
def _remove(package_name, time_out):
"""Removes a package.
Returns OK if the package is removed successfully or a result code if a
recoverable-error occurs.
Raises an exception if a non-recoverable error or time out occurs.
"""
child = pexpect.spawn("sudo -E apt-get -y --allow-unauthenticated "
"remove %s" % package_name)
try:
i = child.expect(['.*password*',
'E: Unable to locate package %s' % package_name,
'Package is in a very bad inconsistent state',
("Sub-process /usr/bin/dpkg returned an error "
"code"),
("dpkg was interrupted, you must manually run "
"'sudo dpkg --configure -a'"),
"Unable to lock the administration directory",
#'The following packages will be REMOVED',
"Removing %s*" % package_name],
timeout=time_out)
if i == 0:
raise PkgPermissionError("Invalid permissions.")
elif i == 1:
raise PkgNotFoundError("Could not find pkg %s" % package_name)
elif i == 2 or i == 3:
return REINSTALL_FIRST
elif i == 4:
return RUN_DPKG_FIRST
elif i == 5:
raise PkgAdminLockError()
wait_and_close_proc(child)
except pexpect.TIMEOUT:
kill_proc(child)
raise PkgTimeout("Process timeout after %i seconds." % time_out)
return OK
def pkg_install(package_name, time_out):
"""Installs a package."""
try:
utils.execute("apt-get", "update", run_as_root=True,
root_helper="sudo")
except ProcessExecutionError as e:
LOG.error(_("Error updating the apt sources"))
result = _install(package_name, time_out)
if result != OK:
if result == RUN_DPKG_FIRST:
_fix(time_out)
result = _install(package_name, time_out)
if result != OK:
raise PkgPackageStateError("Package %s is in a bad state."
% package_name)
def pkg_version(package_name):
cmd_list = ["dpkg", "-l", package_name]
p = commands.getstatusoutput(' '.join(cmd_list))
# check the command status code
if not p[0] == 0:
return None
# Need to capture the version string
# check the command output
std_out = p[1]
patterns = ['.*No packages found matching.*',
"\w\w\s+(\S+)\s+(\S+)\s+(.*)$"]
for line in std_out.split("\n"):
for p in patterns:
regex = re.compile(p)
matches = regex.match(line)
if matches:
line = matches.group()
parts = line.split()
if not parts:
msg = _("returned nothing")
LOG.error(msg)
raise exception.GuestError(msg)
if len(parts) <= 2:
msg = _("Unexpected output.")
LOG.error(msg)
raise exception.GuestError(msg)
if parts[1] != package_name:
msg = _("Unexpected output:[1] = %s" % str(parts[1]))
LOG.error(msg)
raise exception.GuestError(msg)
if parts[0] == 'un' or parts[2] == '<none>':
return None
return parts[2]
msg = _("version() saw unexpected output from dpkg!")
LOG.error(msg)
raise exception.GuestError(msg)
def pkg_remove(package_name, time_out):
"""Removes a package."""
if pkg_version(package_name) is None:
return
result = _remove(package_name, time_out)
if result != OK:
if result == REINSTALL_FIRST:
_install(package_name, time_out)
elif result == RUN_DPKG_FIRST:
_fix(time_out)
result = _remove(package_name, time_out)
if result != OK:
raise PkgPackageStateError("Package %s is in a bad state."
% package_name)