Add support to create a Keystone domain for Heat
Heat in Kilo will require configuration that specifies a domain that is set up in Keystone in its configuration. To facilitate that undeprecate initialize_for_heat(), wean it off its use of the admin token, and add a CLI utility to make calling it from -incubator easy. Change-Id: Ifae32d806575fd48cc7d261deedd94efb5511d0d
This commit is contained in:
parent
f811472c5f
commit
601d7bdc16
53
os_cloud_config/cmd/init_keystone_heat_domain.py
Normal file
53
os_cloud_config/cmd/init_keystone_heat_domain.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||||
|
#
|
||||||
|
# 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 argparse
|
||||||
|
import logging
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
import os_cloud_config.cmd.utils._clients as clients
|
||||||
|
from os_cloud_config.cmd.utils import environment
|
||||||
|
from os_cloud_config.keystone import initialize_for_heat
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
description = textwrap.dedent("""
|
||||||
|
Create a domain for Heat to use, as well as a user to administer it.
|
||||||
|
|
||||||
|
This will create a heat domain in Keystone, as well as an admin user that
|
||||||
|
has rights to administer the domain.
|
||||||
|
""")
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
description=description)
|
||||||
|
parser.add_argument('-d', '--domain-admin-password',
|
||||||
|
dest='domain_admin_password',
|
||||||
|
help="domain admin user's password to be set",
|
||||||
|
required=True)
|
||||||
|
environment._add_logging_arguments(parser)
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = parse_args()
|
||||||
|
environment._configure_logging(args)
|
||||||
|
try:
|
||||||
|
environment._ensure()
|
||||||
|
keystone_client = clients.get_keystone_v3_client()
|
||||||
|
initialize_for_heat(keystone_client, args.domain_admin_password)
|
||||||
|
except Exception:
|
||||||
|
logging.exception("Unexpected error during command execution")
|
||||||
|
return 1
|
||||||
|
return 0
|
35
os_cloud_config/cmd/tests/test_init_keystone_heat_domain.py
Normal file
35
os_cloud_config/cmd/tests/test_init_keystone_heat_domain.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||||
|
#
|
||||||
|
# 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 sys
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from os_cloud_config.cmd import init_keystone_heat_domain
|
||||||
|
from os_cloud_config.tests import base
|
||||||
|
|
||||||
|
|
||||||
|
class InitKeystoneHeatDomainTest(base.TestCase):
|
||||||
|
|
||||||
|
@mock.patch('os_cloud_config.cmd.init_keystone_heat_domain.environment')
|
||||||
|
@mock.patch('os_cloud_config.cmd.init_keystone_heat_domain'
|
||||||
|
'.initialize_for_heat')
|
||||||
|
@mock.patch('os_cloud_config.cmd.utils._clients.get_keystone_v3_client',
|
||||||
|
return_value='keystone_v3_client_mock')
|
||||||
|
@mock.patch.object(sys, 'argv', ['init-keystone', '-d', 'password'])
|
||||||
|
def test_script(self, environment_mock, initialize_mock, client_mock):
|
||||||
|
init_keystone_heat_domain.main()
|
||||||
|
initialize_mock.assert_called_once_with('keystone_v3_client_mock',
|
||||||
|
'password')
|
@ -161,27 +161,25 @@ def initialize_for_swift(host, admin_token, ssl=None, public=None):
|
|||||||
keystone.roles.create('ResellerAdmin')
|
keystone.roles.create('ResellerAdmin')
|
||||||
|
|
||||||
|
|
||||||
def initialize_for_heat(host, admin_token, domain_admin_password,
|
def initialize_for_heat(keystone, domain_admin_password):
|
||||||
ssl=None, public=None):
|
|
||||||
"""Create Heat domain and an admin user for it.
|
"""Create Heat domain and an admin user for it.
|
||||||
|
|
||||||
:param host: ip/hostname of node where Keystone is running
|
:param keystone: A keystone v3 client
|
||||||
:param admin_token: admin token to use with Keystone's admin endpoint
|
|
||||||
:param domain_admin_password: heat domain admin's password to be set
|
:param domain_admin_password: heat domain admin's password to be set
|
||||||
:param ssl: ip/hostname to use as the ssl endpoint, if required
|
|
||||||
:param public: ip/hostname to use as the public endpoint, if the default
|
|
||||||
is not suitable
|
|
||||||
"""
|
"""
|
||||||
LOG.warn('This function is deprecated.')
|
try:
|
||||||
|
heat_domain = keystone.domains.find(name='heat')
|
||||||
keystone = _create_admin_client_v2(host, admin_token, ssl, public)
|
LOG.debug('Domain heat already exists.')
|
||||||
admin_role = keystone.roles.find(name='admin')
|
except exceptions.NotFound:
|
||||||
|
|
||||||
LOG.debug('Creating heat domain.')
|
LOG.debug('Creating heat domain.')
|
||||||
heat_domain = keystone.domains.create(
|
heat_domain = keystone.domains.create(
|
||||||
'heat',
|
'heat',
|
||||||
description='Owns users and tenants created by heat'
|
description='Owns users and tenants created by heat'
|
||||||
)
|
)
|
||||||
|
try:
|
||||||
|
heat_admin = keystone.users.find(name='heat_domain_admin')
|
||||||
|
LOG.debug('Heat domain admin already exists.')
|
||||||
|
except exceptions.NotFound:
|
||||||
LOG.debug('Creating heat_domain_admin user.')
|
LOG.debug('Creating heat_domain_admin user.')
|
||||||
heat_admin = keystone.users.create(
|
heat_admin = keystone.users.create(
|
||||||
'heat_domain_admin',
|
'heat_domain_admin',
|
||||||
@ -190,6 +188,7 @@ def initialize_for_heat(host, admin_token, domain_admin_password,
|
|||||||
password=domain_admin_password,
|
password=domain_admin_password,
|
||||||
)
|
)
|
||||||
LOG.debug('Granting admin role to heat_domain_admin user on heat domain.')
|
LOG.debug('Granting admin role to heat_domain_admin user on heat domain.')
|
||||||
|
admin_role = keystone.roles.find(name='admin')
|
||||||
keystone.roles.grant(admin_role, user=heat_admin, domain=heat_domain)
|
keystone.roles.grant(admin_role, user=heat_admin, domain=heat_domain)
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,22 +77,24 @@ class KeystoneTest(base.TestCase):
|
|||||||
[mock.call('swiftoperator'), mock.call('ResellerAdmin')])
|
[mock.call('swiftoperator'), mock.call('ResellerAdmin')])
|
||||||
|
|
||||||
def test_initialize_for_heat(self):
|
def test_initialize_for_heat(self):
|
||||||
self._patch_client()
|
client = mock.MagicMock()
|
||||||
|
client.domains.find.side_effect = exceptions.NotFound
|
||||||
|
client.users.find.side_effect = exceptions.NotFound
|
||||||
|
|
||||||
keystone.initialize_for_heat('192.0.0.3', 'mytoken', 'heatadminpasswd')
|
keystone.initialize_for_heat(client, 'heatadminpasswd')
|
||||||
|
|
||||||
self.client.domains.create.assert_called_once_with(
|
client.domains.create.assert_called_once_with(
|
||||||
'heat', description='Owns users and tenants created by heat')
|
'heat', description='Owns users and tenants created by heat')
|
||||||
self.client.users.create.assert_called_once_with(
|
client.users.create.assert_called_once_with(
|
||||||
'heat_domain_admin',
|
'heat_domain_admin',
|
||||||
description='Manages users and tenants created by heat',
|
description='Manages users and tenants created by heat',
|
||||||
domain=self.client.domains.create.return_value,
|
domain=client.domains.create.return_value,
|
||||||
password='heatadminpasswd')
|
password='heatadminpasswd')
|
||||||
self.client.roles.find.assert_called_once_with(name='admin')
|
client.roles.find.assert_called_once_with(name='admin')
|
||||||
self.client.roles.grant.assert_called_once_with(
|
client.roles.grant.assert_called_once_with(
|
||||||
self.client.roles.find.return_value,
|
client.roles.find.return_value,
|
||||||
user=self.client.users.create.return_value,
|
user=client.users.create.return_value,
|
||||||
domain=self.client.domains.create.return_value)
|
domain=client.domains.create.return_value)
|
||||||
|
|
||||||
@mock.patch('subprocess.check_call')
|
@mock.patch('subprocess.check_call')
|
||||||
def test_idempotent_initialize(self, check_call_mock):
|
def test_idempotent_initialize(self, check_call_mock):
|
||||||
|
@ -27,6 +27,7 @@ packages =
|
|||||||
console_scripts =
|
console_scripts =
|
||||||
generate-keystone-pki = os_cloud_config.cmd.generate_keystone_pki:main
|
generate-keystone-pki = os_cloud_config.cmd.generate_keystone_pki:main
|
||||||
init-keystone = os_cloud_config.cmd.init_keystone:main
|
init-keystone = os_cloud_config.cmd.init_keystone:main
|
||||||
|
init-keystone-heat-domain = os_cloud_config.cmd.init_keystone_heat_domain:main
|
||||||
register-nodes = os_cloud_config.cmd.register_nodes:main
|
register-nodes = os_cloud_config.cmd.register_nodes:main
|
||||||
setup-endpoints = os_cloud_config.cmd.setup_endpoints:main
|
setup-endpoints = os_cloud_config.cmd.setup_endpoints:main
|
||||||
setup-flavors = os_cloud_config.cmd.setup_flavors:main
|
setup-flavors = os_cloud_config.cmd.setup_flavors:main
|
||||||
|
Loading…
Reference in New Issue
Block a user