import logging
import ast
+import re
from cStringIO import StringIO
)
return pkg_name
+
+
+def get_package_version(remote, package):
+ installed_ver = None
+ if remote.os.package_type == "deb":
+ proc = remote.run(
+ args=[
+ 'dpkg-query', '-W', '-f', '${Version}', package
+ ],
+ stdout=StringIO(),
+ )
+ else:
+ proc = remote.run(
+ args=[
+ 'rpm', '-q', package, '--qf', '%{VERSION}'
+ ],
+ stdout=StringIO(),
+ )
+ if proc.exitstatus == 0:
+ installed_ver = proc.stdout.getvalue().strip()
+ # Does this look like a version string?
+ # this assumes a version string starts with non-alpha characters
+ if installed_ver and re.match('^[^a-zA-Z]', installed_ver):
+ log.info("The installed version of {pkg} is {ver}".format(
+ pkg=package,
+ ver=installed_ver,
+ ))
+ else:
+ installed_ver = None
+ else:
+ # should this throw an exception and stop the job?
+ log.warning(
+ "Unable to determine if {pkg} is installed: {stdout}".format(
+ pkg=package,
+ stdout=proc.stdout.getvalue().strip(),
+ )
+ )
+
+ return installed_ver
from teuthology.config import config as teuth_config
from teuthology import misc as teuthology
-from teuthology import contextutil
+from teuthology import contextutil, packaging
from teuthology.exceptions import VersionNotFoundError
from teuthology.parallel import parallel
from ..orchestra import run
raise VersionNotFoundError(base_url)
break
version = r.stdout.getvalue().strip()
+ # FIXME: 'version' as retreived from the repo is actually the RPM version
+ # PLUS *part* of the release. Example:
+ # Right now, ceph master is given the following version in the repo file:
+ # v0.67-rc3.164.gd5aa3a9 - whereas in reality the RPM version is 0.61.7
+ # and the release is 37.g1243c97.el6 (for centos6).
+ # Point being, I have to mangle a little here.
+ if version[0] == 'v':
+ version = version[1:]
+ if '-' in version:
+ version = version.split('-')[0]
return version
def _get_local_dir(config, remote):
run.Raw(';'), 'fi'])
+def verify_ceph_version(ctx, config, remote):
+ """
+ Ensures that the version of ceph installed is what
+ was asked for in the config.
+ """
+ base_url = _get_baseurl(ctx, remote, config)
+ version = _block_looking_for_package_version(
+ remote,
+ base_url,
+ config.get('wait_for_package', False)
+ )
+ installed_ver = packaging.get_package_version(remote, 'ceph')
+ if installed_ver and version in installed_ver:
+ msg = "The correct ceph version {ver} is installed.".format(
+ ver=version
+ )
+ log.info(msg)
+ else:
+ raise RuntimeError(
+ "Ceph version {ver} was not installed, found {installed}.".format(
+ ver=version,
+ installed=installed_ver
+ )
+ )
+
+
def purge_data(ctx):
"""
Purge /var/lib/ceph on every remote in ctx.
install_pkgs[system_type],
ctx, remote, pkgs[system_type], config)
+ for remote in ctx.cluster.remotes.iterkeys():
+ # verifies that the install worked as expected
+ verify_ceph_version(ctx, config, remote)
+
def _remove_deb(ctx, config, remote, debs):
"""
arch=distinfo['arch'],)
)
- log.info("Getting version and release for the currently installed ceph...")
- remote.run(args=[
- 'rpm', '-q', 'ceph', '--qf', '%{VERSION}-%{RELEASE}'
- ])
base_url = _get_baseurl(ctx, remote, config)
log.info('Repo base URL: %s', base_url)
project = config.get('project', 'ceph')
args = ['sudo', 'yum', '-y', 'install']
args += pkgs
remote.run(args=args)
- log.info("Getting version and release for the newly upgraded ceph...")
- remote.run(args=[
- 'rpm', '-q', 'ceph', '--qf', '%{VERSION}-%{RELEASE}'
- ])
def upgrade_old_style(ctx, node, remote, pkgs, system_type):
node['project'] = project
deploy_style(ctx, node, remote, pkgs, system_type)
+ verify_ceph_version(ctx, node, remote)
docstring_for_upgrade = """"
--- /dev/null
+import pytest
+
+from mock import patch, Mock
+
+from teuthology.task import install
+
+
+class TestInstall(object):
+
+ @patch("teuthology.task.install._get_baseurl")
+ @patch("teuthology.task.install._block_looking_for_package_version")
+ @patch("teuthology.task.install.packaging.get_package_version")
+ def test_verify_ceph_version_success(self, m_get_package_version, m_block,
+ m_get_baseurl):
+ m_block.return_value = "0.89.0"
+ m_get_package_version.return_value = "0.89.0"
+ install.verify_ceph_version(Mock(), Mock(), Mock())
+
+ @patch("teuthology.task.install._get_baseurl")
+ @patch("teuthology.task.install._block_looking_for_package_version")
+ @patch("teuthology.task.install.packaging.get_package_version")
+ def test_verify_ceph_version_failed(self, m_get_package_version, m_block,
+ m_get_baseurl):
+ m_block.return_value = "0.89.0"
+ m_get_package_version.return_value = "0.89.1"
+ with pytest.raises(RuntimeError):
+ install.verify_ceph_version(Mock(), Mock(), Mock())
m_ctx.summary = dict()
with pytest.raises(RuntimeError):
packaging.get_koji_build_info(1, m_remote, m_ctx)
+
+ def test_get_package_version_deb_found(self):
+ remote = Mock()
+ remote.os.package_type = "deb"
+ proc = Mock()
+ proc.exitstatus = 0
+ proc.stdout.getvalue.return_value = "2.2"
+ remote.run.return_value = proc
+ result = packaging.get_package_version(remote, "apache2")
+ assert result == "2.2"
+
+ def test_get_package_version_deb_command(self):
+ remote = Mock()
+ remote.os.package_type = "deb"
+ packaging.get_package_version(remote, "apache2")
+ args, kwargs = remote.run.call_args
+ expected_args = ['dpkg-query', '-W', '-f', '${Version}', 'apache2']
+ assert expected_args == kwargs['args']
+
+ def test_get_package_version_rpm_found(self):
+ remote = Mock()
+ remote.os.package_type = "rpm"
+ proc = Mock()
+ proc.exitstatus = 0
+ proc.stdout.getvalue.return_value = "2.2"
+ remote.run.return_value = proc
+ result = packaging.get_package_version(remote, "httpd")
+ assert result == "2.2"
+
+ def test_get_package_version_rpm_command(self):
+ remote = Mock()
+ remote.os.package_type = "rpm"
+ packaging.get_package_version(remote, "httpd")
+ args, kwargs = remote.run.call_args
+ expected_args = ['rpm', '-q', 'httpd', '--qf', '%{VERSION}']
+ assert expected_args == kwargs['args']
+
+ def test_get_package_version_not_found(self):
+ remote = Mock()
+ remote.os.package_type = "rpm"
+ proc = Mock()
+ proc.exitstatus = 1
+ proc.stdout.getvalue.return_value = "not installed"
+ remote.run.return_value = proc
+ result = packaging.get_package_version(remote, "httpd")
+ assert result is None
+
+ def test_get_package_version_invalid_version(self):
+ # this tests the possibility that the package is not found
+ # but the exitstatus is still 0. Not entirely sure we'll ever
+ # hit this condition, but I want to test the codepath regardless
+ remote = Mock()
+ remote.os.package_type = "rpm"
+ proc = Mock()
+ proc.exitstatus = 0
+ proc.stdout.getvalue.return_value = "not installed"
+ remote.run.return_value = proc
+ result = packaging.get_package_version(remote, "httpd")
+ assert result is None