Add deploy from source action support and various fixups after rebase

This commit is contained in:
Corey Bryant 2015-03-13 09:52:11 +00:00
parent b0bec63637
commit ece7c05e39
19 changed files with 203 additions and 154 deletions

View File

@ -2,7 +2,7 @@
PYTHON := /usr/bin/env python
lint:
@flake8 --exclude hooks/charmhelpers hooks unit_tests tests
@flake8 --exclude hooks/charmhelpers actions/* hooks unit_tests tests
@charm proof
unit_test:
@ -15,7 +15,9 @@ test:
# raise_status() messages to stderr:
# https://bugs.launchpad.net/amulet/+bug/1320357
@juju test -v -p AMULET_HTTP_PROXY --timeout 900 \
00-setup 14-basic-precise-icehouse 15-basic-trusty-icehouse
00-setup 14-basic-precise-icehouse 15-basic-trusty-icehouse \
16-basic-trusty-icehouse-git 17-basic-trusty-juno \
18-basic-trusty-juno-git
bin/charm_helpers_sync.py:
@mkdir -p bin
@ -26,6 +28,6 @@ sync: bin/charm_helpers_sync.py
@$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers-hooks.yaml
@$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers-tests.yaml
publish: lint test
publish: lint unit_test
bzr push lp:charms/keystone
bzr push lp:charms/trusty/keystone

View File

@ -74,65 +74,56 @@ Deploying from source
The minimal openstack-origin-git config required to deploy from source is:
openstack-origin-git:
"{'keystone':
{'repository': 'git://git.openstack.org/openstack/keystone.git',
'branch': 'stable/icehouse'}}"
If you specify a 'requirements' repository, it will be used to update the
requirements.txt files of all other git repos that it applies to, before
they are installed:
openstack-origin-git:
"{'requirements':
{'repository': 'git://git.openstack.org/openstack/requirements.git',
'branch': 'master'},
'keystone':
{'repository': 'git://git.openstack.org/openstack/keystone.git',
'branch': 'master'}}"
"{requirements:
{repository: 'git://git.openstack.org/openstack/requirements.git',
branch: master},
keystone:
{repository: 'git://git.openstack.org/openstack/keystone.git',
branch: master}}"
Note that there are only two key values the charm knows about for the outermost
dictionary: 'keystone' and 'requirements'. These repositories must correspond to
these keys. If the requirements repository is specified, it will be installed
first. The keystone repository is always installed last. All other repostories
will be installed in between.
these keys. The requirements repository will always be installed first. The
keystone repository is always installed last. All other repostories will be
installed in between.
NOTE(coreycb): The following is temporary to keep track of the full list of
current tip repos (may not be up-to-date).
openstack-origin-git:
"{'requirements':
{'repository': 'git://git.openstack.org/openstack/requirements.git',
'branch': 'master'},
'keystonemiddleware:
{'repository': 'git://git.openstack.org/openstack/keystonemiddleware.git',
'branch: 'master'},
'oslo-concurrency':
{'repository': 'git://git.openstack.org/openstack/oslo.concurrency.git',
'branch: 'master'},
'oslo-config':
{'repository': 'git://git.openstack.org/openstack/oslo.config.git',
'branch: 'master'},
'oslo-db':
{'repository': 'git://git.openstack.org/openstack/oslo.db.git',
'branch: 'master'},
'oslo-i18n':
{'repository': 'git://git.openstack.org/openstack/oslo.i18n.git',
'branch: 'master'},
'oslo-serialization':
{'repository': 'git://git.openstack.org/openstack/oslo.serialization.git',
'branch: 'master'},
'oslo-utils':
{'repository': 'git://git.openstack.org/openstack/oslo.utils.git',
'branch: 'master'},
'pbr':
{'repository': 'git://git.openstack.org/openstack-dev/pbr.git',
'branch: 'master'},
'python-keystoneclient':
{'repository': 'git://git.openstack.org/openstack/python-keystoneclient.git',
'branch: 'master'},
'sqlalchemy-migrate':
{'repository': 'git://git.openstack.org/stackforge/sqlalchemy-migrate.git',
'branch: 'master'},
'keystone':
{'repository': 'git://git.openstack.org/openstack/keystone.git',
'branch': 'master'}}"
"{requirements:
{repository: 'git://git.openstack.org/openstack/requirements.git',
branch: master},
keystonemiddleware:
{repository: 'git://git.openstack.org/openstack/keystonemiddleware.git',
branch: master},
oslo-concurrency:
{repository: 'git://git.openstack.org/openstack/oslo.concurrency.git',
branch: master},
oslo-config:
{repository: 'git://git.openstack.org/openstack/oslo.config.git',
branch: master},
oslo-db:
{repository: 'git://git.openstack.org/openstack/oslo.db.git',
branch: master},
oslo-i18n:
{repository: 'git://git.openstack.org/openstack/oslo.i18n.git',
branch: master},
oslo-serialization:
{repository: 'git://git.openstack.org/openstack/oslo.serialization.git',
branch: master},
oslo-utils:
{repository: 'git://git.openstack.org/openstack/oslo.utils.git',
branch: master},
pbr:
{repository: 'git://git.openstack.org/openstack-dev/pbr.git',
branch: master},
python-keystoneclient:
{repository: 'git://git.openstack.org/openstack/python-keystoneclient.git',
branch: master},
sqlalchemy-migrate:
{repository: 'git://git.openstack.org/stackforge/sqlalchemy-migrate.git',
branch: master},
keystone:
{repository: 'git://git.openstack.org/openstack/keystone.git',
branch: master}}"

2
actions.yaml Normal file
View File

@ -0,0 +1,2 @@
git-reinstall:
description: Reinstall openstack-origin-git repos and restart services

35
actions/git-reinstall Executable file
View File

@ -0,0 +1,35 @@
#!/usr/bin/python
import sys
sys.path.append('hooks/')
from charmhelpers.contrib.openstack.utils import (
git_install_requested,
)
from charmhelpers.core.hookenv import (
action_set,
action_fail,
config,
)
from keystone_utils import (
git_install,
)
def git_reinstall():
"""Reinstall from source and restart services.
If the openstack-origin-git config option was used to install openstack
from source git repositories, then this action can be used to reinstall
from updated git repositories, followed by a restart of services."""
if not git_install_requested():
action_fail("openstack-origin-git is not configured")
git_install(config('openstack-origin-git'))
action_set({'status': "git-reinstall action completed"})
if __name__ == '__main__':
git_reinstall()

View File

@ -1,5 +1,4 @@
#branch: lp:charm-helpers
branch: /home/corey/src/charms/git/charm-helpers
branch: lp:charm-helpers
destination: hooks/charmhelpers
include:
- core

View File

@ -1,5 +1,4 @@
#branch: lp:charm-helpers
branch: /home/corey/src/charms/git/charm-helpers
branch: lp:charm-helpers
destination: tests/charmhelpers
include:
- contrib.amulet

View File

@ -34,12 +34,12 @@ options:
repositories and branches from which to install OpenStack and its
dependencies.
This option is processed for the initial install only. Setting
this option after deployment is not supported.
Note that the installed config files will be determined based on
the OpenStack release of the openstack-origin option.
Note also that this option is processed for the initial install
only. Setting this option after deployment is not supported.
For more details see README.md.
config-file:
default: "/etc/keystone/keystone.conf"

View File

@ -114,8 +114,7 @@ def install():
apt_update()
apt_install(determine_packages(), fatal=True)
# NOTE(coreycb): This is temporary for sstack proxy, unless we decide
# we need to code proxy support into the charms.
# NOTE(coreycb): This is temporary until bug #1431286 is fixed.
os.environ["http_proxy"] = "http://squid.internal:3128"
os.environ["https_proxy"] = "https://squid.internal:3128"
@ -171,12 +170,6 @@ def config_changed():
ha_joined(relation_id=r_id)
#TODO(coreycb): For deploy from git support, need to implement action-set
# and action-get to trigger re-install of git-installed
# services. IIUC they'd be triggered via:
# juju do <action> <parameters>
@hooks.hook('shared-db-relation-joined')
def db_joined():
if is_relation_made('pgsql-db'):

View File

@ -47,11 +47,6 @@ from charmhelpers.contrib.openstack.utils import (
os_release,
save_script_rc as _save_script_rc)
from charmhelpers.core.host import (
mkdir,
write_file,
)
from charmhelpers.core.strutils import (
bool_from_string,
)
@ -331,6 +326,7 @@ def determine_packages():
if git_install_requested():
packages.extend(BASE_GIT_PACKAGES)
# don't include packages that will be installed from git
packages = list(set(packages))
for p in GIT_PACKAGE_BLACKLIST:
packages.remove(p)
@ -903,7 +899,7 @@ def is_ssl_enabled():
return True
log("SSL/HTTPS is NOT enabled", level=DEBUG)
return True
return False
def get_ssl_cert_master_votes():
@ -1552,7 +1548,7 @@ def git_install(projects):
def git_pre_install():
"""Perform pre keystone installation setup."""
"""Perform keystone pre-install setup."""
dirs = [
'/var/lib/keystone',
'/var/lib/keystone/cache',
@ -1576,13 +1572,10 @@ def git_pre_install():
def git_post_install():
"""Perform post keystone installation setup."""
"""Perform keystone post-install setup."""
# NOTE(coreycb): Should the mount point be a config option?
src_etc = os.path.join(charm_dir(), '/mnt/openstack-git/keystone.git/etc/')
configs = {
'keystone': {
'src': os.path.join(src_etc, 'keystone.conf.sample'),
'dest': '/etc/keystone/keystone.conf',
},
'policy': {
'src': os.path.join(src_etc, 'policy.json'),
'dest': '/etc/keystone/policy.json',
@ -1610,4 +1603,4 @@ def git_post_install():
render('upstart/keystone.upstart', '/etc/init/keystone.conf',
keystone_context, perms=0o644)
service_start('keystone')
service_restart('keystone')

View File

@ -1,9 +0,0 @@
#!/usr/bin/python
"""Amulet tests on a basic keystone deployment on precise-essex."""
from basic_deployment import KeystoneBasicDeployment
if __name__ == '__main__':
deployment = KeystoneBasicDeployment(series='precise')
deployment.run_tests()

View File

@ -1,11 +0,0 @@
#!/usr/bin/python
"""Amulet tests on a basic keystone deployment on precise-folsom."""
from basic_deployment import KeystoneBasicDeployment
if __name__ == '__main__':
deployment = KeystoneBasicDeployment(series='precise',
openstack='cloud:precise-folsom',
source='cloud:precise-updates/folsom')
deployment.run_tests()

View File

@ -1,11 +0,0 @@
#!/usr/bin/python
"""Amulet tests on a basic keystone deployment on precise-grizzly."""
from basic_deployment import KeystoneBasicDeployment
if __name__ == '__main__':
deployment = KeystoneBasicDeployment(series='precise',
openstack='cloud:precise-grizzly',
source='cloud:precise-updates/grizzly')
deployment.run_tests()

View File

@ -1,11 +0,0 @@
#!/usr/bin/python
"""Amulet tests on a basic keystone deployment on precise-havana."""
from basic_deployment import KeystoneBasicDeployment
if __name__ == '__main__':
deployment = KeystoneBasicDeployment(series='precise',
openstack='cloud:precise-havana',
source='cloud:precise-updates/havana')
deployment.run_tests()

View File

@ -0,0 +1,9 @@
#!/usr/bin/python
"""Amulet tests on a basic keystone git deployment on trusty-icehouse."""
from basic_deployment import KeystoneBasicDeployment
if __name__ == '__main__':
deployment = KeystoneBasicDeployment(series='trusty', git=True)
deployment.run_tests()

11
tests/17-basic-trusty-juno Executable file
View File

@ -0,0 +1,11 @@
#!/usr/bin/python
"""Amulet tests on a basic keystone deployment on trusty-juno."""
from basic_deployment import KeystoneBasicDeployment
if __name__ == '__main__':
deployment = KeystoneBasicDeployment(series='trusty',
openstack='cloud:trusty-juno',
source='cloud:trusty-updates/juno')
deployment.run_tests()

12
tests/18-basic-trusty-juno-git Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/python
"""Amulet tests on a basic keystone git deployment on trusty-juno."""
from basic_deployment import KeystoneBasicDeployment
if __name__ == '__main__':
deployment = KeystoneBasicDeployment(series='trusty',
openstack='cloud:trusty-juno',
source='cloud:trusty-updates/juno',
git=True)
deployment.run_tests()

View File

@ -1,6 +1,7 @@
#!/usr/bin/python
import amulet
import yaml
from charmhelpers.contrib.openstack.amulet.deployment import (
OpenStackAmuletDeployment
@ -19,9 +20,10 @@ u = OpenStackAmuletUtils(ERROR)
class KeystoneBasicDeployment(OpenStackAmuletDeployment):
"""Amulet tests on a basic keystone deployment."""
def __init__(self, series=None, openstack=None, source=None, stable=False):
def __init__(self, series=None, openstack=None, source=None, git=False, stable=False):
"""Deploy the entire test environment."""
super(KeystoneBasicDeployment, self).__init__(series, openstack, source, stable)
self.git = git
self._add_services()
self._add_relations()
self._configure_services()
@ -49,12 +51,20 @@ class KeystoneBasicDeployment(OpenStackAmuletDeployment):
def _configure_services(self):
"""Configure all of the services."""
keystone_config = {'admin-password': 'openstack',
'admin-token': 'ubuntutesting',
# NOTE(coreycb): Added the following temporarily to test deploy from source
'openstack-origin-git':
"{'keystone':"
" {'repository': 'git://git.openstack.org/openstack/keystone.git',"
" 'branch': 'stable/icehouse'}}"}
'admin-token': 'ubuntutesting'}
if self.git:
openstack_origin_git = {
'keystone': {
'repository': 'git://git.openstack.org/openstack/keystone.git',
'branch': 'stable/icehouse'
},
'requirements': {
'repository': 'git://git.openstack.org/openstack/requirements.git',
'branch': 'master'
},
}
keystone_config['openstack-origin-git'] = yaml.dump(openstack_origin_git)
mysql_config = {'dataset-size': '50%'}
cinder_config = {'block-device': 'None'}
configs = {'keystone': keystone_config,

View File

@ -2,6 +2,7 @@ from mock import call, patch, MagicMock
import os
import json
import uuid
import yaml
from test_utils import CharmTestCase
@ -82,9 +83,7 @@ class KeystoneRelationTests(CharmTestCase):
def test_install_hook(self, git_requested):
git_requested.return_value = False
repo = 'cloud:precise-grizzly'
git_config = 'config/git-tip-minimal.yaml'
self.test_config.set('openstack-origin', repo)
self.test_config.set('openstack-origin-git', git_config)
hooks.install()
self.assertTrue(self.execd_preinstall.called)
self.configure_installation_source.assert_called_with(repo)
@ -93,13 +92,19 @@ class KeystoneRelationTests(CharmTestCase):
['haproxy', 'unison', 'python-keystoneclient',
'uuid', 'python-mysqldb', 'openssl', 'apache2',
'pwgen', 'python-six', 'keystone', 'python-psycopg2'], fatal=True)
self.git_install.assert_called_with(git_config)
self.git_install.assert_called_with('None')
@patch.object(utils, 'git_install_requested')
def test_install_hook_git(self, git_requested):
git_requested.return_value = True
repo = 'cloud:precise-grizzly'
git_config = 'config/git-tip-minimal.yaml'
repo = 'cloud:trusty-juno'
openstack_origin_git = {
'keystone': {
'repository': 'git://git.openstack.org/openstack/keystone.git',
'branch': 'stable/juno'
}
}
git_config = yaml.dump(openstack_origin_git)
self.test_config.set('openstack-origin', repo)
self.test_config.set('openstack-origin-git', git_config)
hooks.install()
@ -107,7 +112,7 @@ class KeystoneRelationTests(CharmTestCase):
self.configure_installation_source.assert_called_with(repo)
self.assertTrue(self.apt_update.called)
self.apt_install.assert_called_with(
['haproxy', 'unison', 'python-setuptools', 'uuid',
['haproxy', 'unison', 'python-setuptools', 'python-six', 'uuid',
'python-mysqldb', 'python-pip', 'openssl', 'apache2', 'pwgen',
'libxslt1-dev', 'python-psycopg2', 'zlib1g-dev', 'python-dev',
'libxml2-dev'], fatal=True)
@ -401,6 +406,7 @@ class KeystoneRelationTests(CharmTestCase):
mock_send_ssl_sync_request,
mock_ensure_ssl_cert_master,
mock_log, git_requested):
git_requested.return_value = False
mock_is_db_ready.return_value = True
mock_is_db_initialised.return_value = True
self.openstack_upgrade_available.return_value = True
@ -430,6 +436,14 @@ class KeystoneRelationTests(CharmTestCase):
admin_relation_changed.assert_called_with('identity-service:0')
@patch.object(hooks, 'git_install_requested')
@patch('keystone_utils.log')
@patch('keystone_utils.ensure_ssl_cert_master')
@patch.object(hooks, 'send_ssl_sync_request')
@patch.object(hooks, 'is_db_initialised')
@patch.object(hooks, 'is_db_ready')
@patch.object(hooks, 'peer_units')
@patch.object(hooks, 'ensure_permissions')
@patch.object(hooks, 'admin_relation_changed')
@patch.object(hooks, 'cluster_joined')
@patch.object(unison, 'ensure_user')
@patch.object(unison, 'get_homedir')
@ -438,11 +452,21 @@ class KeystoneRelationTests(CharmTestCase):
@patch.object(hooks, 'configure_https')
def test_config_changed_git_no_openstack_upgrade(
self, configure_https, identity_changed,
configs, get_homedir, ensure_user, cluster_joined, git_requested):
configs, get_homedir, ensure_user, cluster_joined,
admin_relation_changed, ensure_permissions,
mock_peer_units, mock_is_db_ready, mock_is_db_initialised,
mock_send_ssl_sync_request, mock_ensure_ssl_cert_master, mock_log,
git_requested):
mock_is_db_initialised.return_value = True
mock_is_db_ready.return_value = True
self.openstack_upgrade_available.return_value = False
self.is_elected_leader.return_value = True
git_requested.return_value = True
self.eligible_leader.return_value = True
# avoid having to mock syncer
mock_ensure_ssl_cert_master.return_value = False
mock_peer_units.return_value = []
self.relation_ids.return_value = ['identity-service:0']
self.relation_list.return_value = ['unit/0']
self.related_units.return_value = ['unit/0']
hooks.config_changed()
ensure_user.assert_called_with(user=self.ssh_user, group='keystone')
@ -455,13 +479,13 @@ class KeystoneRelationTests(CharmTestCase):
configure_https.assert_called_with()
self.assertTrue(configs.write_all.called)
self.migrate_database.assert_called_with()
self.assertTrue(self.ensure_initial_admin.called)
self.log.assert_called_with(
'Firing identity_changed hook for all related services.')
identity_changed.assert_called_with(
relation_id='identity-service:0',
remote_unit='unit/0')
admin_relation_changed.assert_called_with('identity-service:0')
@patch.object(hooks, 'is_db_initialised')
@patch.object(hooks, 'is_db_ready')

View File

@ -2,6 +2,7 @@ from mock import patch, call, MagicMock, Mock
from test_utils import CharmTestCase
import os
import manager
import yaml
os.environ['JUJU_UNIT_NAME'] = 'keystone'
with patch('charmhelpers.core.hookenv.config') as config:
@ -112,12 +113,18 @@ class TestKeystoneUtils(CharmTestCase):
def test_determine_packages(self, _config):
_config.return_value = "None"
result = utils.determine_packages()
ex = utils.BASE_PACKAGES + ['keystone']
ex = utils.BASE_PACKAGES + ['keystone', 'python-keystoneclient']
self.assertEquals(set(ex), set(result))
@patch('charmhelpers.contrib.openstack.utils.config')
def test_determine_packages_git(self, _config):
_config.return_value = "config/git-juno-minimal.yaml"
openstack_origin_git = {
'keystone': {
'repository': 'git://git.openstack.org/openstack/keystone.git',
'branch': 'stable/icehouse'
}
}
_config.return_value = yaml.dump(openstack_origin_git)
result = utils.determine_packages()
ex = utils.BASE_PACKAGES + ['keystone'] + utils.BASE_GIT_PACKAGES
for p in utils.GIT_PACKAGE_BLACKLIST:
@ -546,11 +553,17 @@ class TestKeystoneUtils(CharmTestCase):
@patch.object(utils, 'git_pre_install')
def test_git_install(self, git_pre, git_post, git_clone_and_install,
git_requested):
file_name = 'config/git-tip-minimal.yaml'
openstack_origin_git = {
'keystone': {
'repository': 'git://git.openstack.org/openstack/keystone.git',
'branch': 'stable/icehouse'
}
}
git_yaml = yaml.dump(openstack_origin_git)
git_requested.return_value = True
utils.git_install(file_name)
utils.git_install(git_yaml)
self.assertTrue(git_pre.called)
git_clone_and_install.assert_called_with(file_name,
git_clone_and_install.assert_called_with(openstack_origin_git,
core_project='keystone')
self.assertTrue(git_post.called)
@ -581,18 +594,16 @@ class TestKeystoneUtils(CharmTestCase):
'', owner='keystone', group='keystone',
perms=0600)
@patch.object(utils, 'service_start')
@patch.object(utils, 'service_restart')
@patch.object(utils, 'render')
@patch('shutil.copyfile')
def test_git_post_install(self, copyfile, render, service_start):
def test_git_post_install(self, copyfile, render, service_restart):
utils.git_post_install()
expected = [
call('/mnt/openstack-git/keystone.git/etc/keystone-paste.ini',
'/etc/keystone/keystone-paste.ini'),
call('/mnt/openstack-git/keystone.git/etc/policy.json',
'/etc/keystone/policy.json'),
call('/mnt/openstack-git/keystone.git/etc/keystone.conf.sample',
'/etc/keystone/keystone.conf'),
]
copyfile.assert_has_calls(expected, any_order=True)
keystone_context = {
@ -610,4 +621,4 @@ class TestKeystoneUtils(CharmTestCase):
keystone_context, perms=0o644),
]
self.assertEquals(render.call_args_list, expected)
service_start.assert_called_with('keystone')
service_restart.assert_called_with('keystone')