Implement setup_endpoints needed by overcloud deploy
Change-Id: Ia7fea303ebc19ec12e650c760012c8aed9dd11fa
This commit is contained in:
@@ -24,3 +24,13 @@ class UnsupportedVersion(Exception):
|
|||||||
class Timeout(Exception):
|
class Timeout(Exception):
|
||||||
"""An operation timed out"""
|
"""An operation timed out"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class UnknownService(Exception):
|
||||||
|
"""The service type is unknown"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class NotFound(Exception):
|
||||||
|
"""Resource not found"""
|
||||||
|
pass
|
||||||
|
@@ -15,8 +15,10 @@
|
|||||||
|
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
|
from collections import namedtuple
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
|
from rdomanager_oscplugin import exceptions
|
||||||
from rdomanager_oscplugin import utils
|
from rdomanager_oscplugin import utils
|
||||||
|
|
||||||
|
|
||||||
@@ -293,3 +295,378 @@ class TestWaitForDiscovery(TestCase):
|
|||||||
utils.remove_known_hosts('192.168.0.1')
|
utils.remove_known_hosts('192.168.0.1')
|
||||||
|
|
||||||
mock_check_call.assert_not_called()
|
mock_check_call.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
class TestRegisterEndpoint(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.mock_identity = mock.Mock()
|
||||||
|
|
||||||
|
Project = namedtuple('Project', 'id name')
|
||||||
|
self.mock_identity.projects.list.return_value = [
|
||||||
|
Project(id='123', name='service'),
|
||||||
|
Project(id='234', name='admin')
|
||||||
|
]
|
||||||
|
|
||||||
|
def _role_list_side_effect(*args, **kwargs):
|
||||||
|
Role = namedtuple('Role', 'id name')
|
||||||
|
user = kwargs.get('user')
|
||||||
|
project = kwargs.get('project')
|
||||||
|
|
||||||
|
if user and project:
|
||||||
|
return Role(id='123', name='admin')
|
||||||
|
else:
|
||||||
|
return [
|
||||||
|
Role(id='123', name='admin'),
|
||||||
|
Role(id='345', name='ResellerAdmin'),
|
||||||
|
]
|
||||||
|
self.mock_identity.roles.list.side_effect = _role_list_side_effect
|
||||||
|
|
||||||
|
User = namedtuple('User', 'id name')
|
||||||
|
self.mock_identity.users.list.return_value = [
|
||||||
|
User(id='123', name='nova')
|
||||||
|
]
|
||||||
|
|
||||||
|
self.services_create_mock = mock.Mock()
|
||||||
|
self.mock_identity.services.create.return_value = (
|
||||||
|
self.services_create_mock)
|
||||||
|
|
||||||
|
self.endpoints_create_mock = mock.Mock()
|
||||||
|
self.mock_identity.endpoints.create.return_value = (
|
||||||
|
self.endpoints_create_mock)
|
||||||
|
|
||||||
|
self.users_create_mock = mock.Mock()
|
||||||
|
self.mock_identity.users.create.return_value = (
|
||||||
|
self.users_create_mock)
|
||||||
|
|
||||||
|
def test_unknown_service(self):
|
||||||
|
self.mock_identity.reset_mock()
|
||||||
|
|
||||||
|
self.assertRaises(exceptions.UnknownService,
|
||||||
|
utils.register_endpoint,
|
||||||
|
'unknown_name',
|
||||||
|
'unknown_endpoint_type',
|
||||||
|
'unknown_url',
|
||||||
|
self.mock_identity)
|
||||||
|
|
||||||
|
def test_no_admin_role(self):
|
||||||
|
local_mock_identity = mock.Mock()
|
||||||
|
local_mock_identity.roles.list.return_value = []
|
||||||
|
self.assertRaises(exceptions.NotFound,
|
||||||
|
utils.register_endpoint,
|
||||||
|
'name',
|
||||||
|
'compute',
|
||||||
|
'url',
|
||||||
|
local_mock_identity)
|
||||||
|
|
||||||
|
def test_endpoint_is_dashboard(self):
|
||||||
|
self.mock_identity.reset_mock()
|
||||||
|
|
||||||
|
utils.register_endpoint(
|
||||||
|
'name',
|
||||||
|
'dashboard',
|
||||||
|
'url',
|
||||||
|
self.mock_identity,
|
||||||
|
description='description'
|
||||||
|
)
|
||||||
|
|
||||||
|
self.mock_identity.roles.list.assert_called_once_with()
|
||||||
|
|
||||||
|
self.mock_identity.services.create.assert_called_once_with(
|
||||||
|
name='name',
|
||||||
|
type='dashboard',
|
||||||
|
description='description',
|
||||||
|
enabled=True
|
||||||
|
)
|
||||||
|
|
||||||
|
self.mock_identity.endpoints.create.assert_called_once_with(
|
||||||
|
'regionOne',
|
||||||
|
self.services_create_mock.id,
|
||||||
|
"url/",
|
||||||
|
"url/admin",
|
||||||
|
"url/"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_endpoint_is_not_dashboard(self):
|
||||||
|
self.mock_identity.reset_mock()
|
||||||
|
|
||||||
|
utils.register_endpoint(
|
||||||
|
'nova',
|
||||||
|
'compute',
|
||||||
|
'url',
|
||||||
|
self.mock_identity,
|
||||||
|
description='description'
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not self.mock_identity.users.create.called
|
||||||
|
self.mock_identity.users.list.assert_called_once_with()
|
||||||
|
|
||||||
|
self.mock_identity.projects.list.assert_called_once_with()
|
||||||
|
|
||||||
|
self.mock_identity.roles.list.assert_has_calls([
|
||||||
|
mock.call(),
|
||||||
|
mock.call(user='123', project='123')
|
||||||
|
])
|
||||||
|
|
||||||
|
self.mock_identity.services.create.assert_called_once_with(
|
||||||
|
name='nova',
|
||||||
|
type='compute',
|
||||||
|
description='description',
|
||||||
|
enabled=True
|
||||||
|
)
|
||||||
|
|
||||||
|
self.mock_identity.endpoints.create.assert_called_once_with(
|
||||||
|
'regionOne',
|
||||||
|
self.services_create_mock.id,
|
||||||
|
"url/v2/$(tenant_id)s",
|
||||||
|
"url/v2/$(tenant_id)s",
|
||||||
|
"url/v2/$(tenant_id)s"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_endpoint_is_metering(self):
|
||||||
|
self.mock_identity.reset_mock()
|
||||||
|
|
||||||
|
utils.register_endpoint(
|
||||||
|
'ceilometer',
|
||||||
|
'metering',
|
||||||
|
'url',
|
||||||
|
self.mock_identity,
|
||||||
|
description='description',
|
||||||
|
password='password'
|
||||||
|
)
|
||||||
|
|
||||||
|
self.mock_identity.users.list.assert_called_once_with()
|
||||||
|
|
||||||
|
self.mock_identity.users.create.assert_called_once_with(
|
||||||
|
name='ceilometer',
|
||||||
|
domain=None,
|
||||||
|
default_project='123',
|
||||||
|
password='password',
|
||||||
|
email='nobody@example.com',
|
||||||
|
description=None,
|
||||||
|
enabled=True
|
||||||
|
)
|
||||||
|
self.mock_identity.services.create.assert_called_once_with(
|
||||||
|
name='ceilometer',
|
||||||
|
type='metering',
|
||||||
|
description='description',
|
||||||
|
enabled=True
|
||||||
|
)
|
||||||
|
|
||||||
|
self.mock_identity.endpoints.create.assert_called_once_with(
|
||||||
|
'regionOne',
|
||||||
|
self.services_create_mock.id,
|
||||||
|
"url/",
|
||||||
|
"url/",
|
||||||
|
"url/"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.mock_identity.roles.list.assert_has_calls([
|
||||||
|
mock.call(),
|
||||||
|
mock.call(user=self.users_create_mock.id, project='123'),
|
||||||
|
mock.call(user=self.users_create_mock.id, project='234'),
|
||||||
|
])
|
||||||
|
|
||||||
|
self.mock_identity.projects.list.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
|
class TestSetupEndpoints(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.mock_identity = mock.Mock()
|
||||||
|
|
||||||
|
@mock.patch('rdomanager_oscplugin.utils.register_endpoint')
|
||||||
|
def test_setup_endpoints_all_ssl(self, mock_register_endpoint):
|
||||||
|
passwords = utils.generate_overcloud_passwords()
|
||||||
|
utils.setup_endpoints(
|
||||||
|
'127.0.0.1',
|
||||||
|
passwords,
|
||||||
|
self.mock_identity,
|
||||||
|
region='regionOne',
|
||||||
|
enable_horizon=True,
|
||||||
|
ssl='127.0.0.2'
|
||||||
|
)
|
||||||
|
|
||||||
|
# import sys
|
||||||
|
# print(mock_register_endpoint.mock_calls, file=sys.stderr)
|
||||||
|
mock_register_endpoint.assert_has_calls([
|
||||||
|
mock.call('ceilometer', 'metering', 'https://127.0.0.2:8777',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:13777',
|
||||||
|
description='Ceilometer Service',
|
||||||
|
password=passwords['OVERCLOUD_CEILOMETER_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('cinder', 'volume', 'https://127.0.0.2:8776',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:13776',
|
||||||
|
description='Cinder Volume Service',
|
||||||
|
password=passwords['OVERCLOUD_CINDER_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('cinderv2', 'volumev2', 'https://127.0.0.2:8776',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:13776',
|
||||||
|
description='Cinder Volume Service V2',
|
||||||
|
password=passwords['OVERCLOUD_CINDER_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('ec2', 'ec2', 'https://127.0.0.2:8773',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:13773',
|
||||||
|
description='EC2 Compatibility Layer',
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('glance', 'image', 'https://127.0.0.2:9292',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:13292',
|
||||||
|
description='Glance Image Service',
|
||||||
|
password=passwords['OVERCLOUD_GLANCE_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('heat', 'orchestration', 'https://127.0.0.2:8004',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:13004',
|
||||||
|
description='Heat Service',
|
||||||
|
password=passwords['OVERCLOUD_HEAT_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('neutron', 'network', 'https://127.0.0.2:9696',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:13696',
|
||||||
|
description='Neutron Service',
|
||||||
|
password=passwords['OVERCLOUD_NEUTRON_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('nova', 'compute', 'https://127.0.0.2:8774',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:13774',
|
||||||
|
description='Nova Compute Service',
|
||||||
|
password=passwords['OVERCLOUD_NOVA_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('nova', 'computev3', 'https://127.0.0.2:8774',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:13774',
|
||||||
|
description='Nova Compute Service v3',
|
||||||
|
password=passwords['OVERCLOUD_NOVA_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('swift', 'object-store', 'https://127.0.0.2:8080',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:13080',
|
||||||
|
description='Swift Object Storage Service',
|
||||||
|
password=passwords['OVERCLOUD_SWIFT_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
# Tuskar not enabled yet
|
||||||
|
# mock.call('tuskar', 'management', 'https://127.0.0.2:8585',
|
||||||
|
# self.mock_identity,
|
||||||
|
# internal_url='http://127.0.0.1:8585',
|
||||||
|
# description='Tuskar Service',
|
||||||
|
# password=passwords['OVERCLOUD_TUSKAR_PASSWORD'],
|
||||||
|
# region='regionOne'),
|
||||||
|
mock.call('horizon', 'dashboard', 'http://127.0.0.1:',
|
||||||
|
self.mock_identity,
|
||||||
|
description='OpenStack Dashboard',
|
||||||
|
internal_url='http://127.0.0.1:',
|
||||||
|
region='regionOne')
|
||||||
|
])
|
||||||
|
|
||||||
|
@mock.patch('rdomanager_oscplugin.utils.register_endpoint')
|
||||||
|
def test_setup_endpoints_all_no_ssl(self, mock_register_endpoint):
|
||||||
|
passwords = utils.generate_overcloud_passwords()
|
||||||
|
utils.setup_endpoints(
|
||||||
|
'127.0.0.1',
|
||||||
|
passwords,
|
||||||
|
self.mock_identity,
|
||||||
|
region='regionOne',
|
||||||
|
enable_horizon=True,
|
||||||
|
public='127.0.0.3'
|
||||||
|
)
|
||||||
|
|
||||||
|
# import sys
|
||||||
|
# print(mock_register_endpoint.mock_calls, file=sys.stderr)
|
||||||
|
mock_register_endpoint.assert_has_calls([
|
||||||
|
mock.call('ceilometer', 'metering', 'http://127.0.0.3:8777',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:8777',
|
||||||
|
description='Ceilometer Service',
|
||||||
|
password=passwords['OVERCLOUD_CEILOMETER_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('cinder', 'volume', 'http://127.0.0.3:8776',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:8776',
|
||||||
|
description='Cinder Volume Service',
|
||||||
|
password=passwords['OVERCLOUD_CINDER_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('cinderv2', 'volumev2', 'http://127.0.0.3:8776',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:8776',
|
||||||
|
description='Cinder Volume Service V2',
|
||||||
|
password=passwords['OVERCLOUD_CINDER_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('ec2', 'ec2', 'http://127.0.0.3:8773',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:8773',
|
||||||
|
description='EC2 Compatibility Layer',
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('glance', 'image', 'http://127.0.0.3:9292',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:9292',
|
||||||
|
description='Glance Image Service',
|
||||||
|
password=passwords['OVERCLOUD_GLANCE_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('heat', 'orchestration', 'http://127.0.0.3:8004',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:8004',
|
||||||
|
description='Heat Service',
|
||||||
|
password=passwords['OVERCLOUD_HEAT_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('neutron', 'network', 'http://127.0.0.3:9696',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:9696',
|
||||||
|
description='Neutron Service',
|
||||||
|
password=passwords['OVERCLOUD_NEUTRON_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('nova', 'compute', 'http://127.0.0.3:8774',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:8774',
|
||||||
|
description='Nova Compute Service',
|
||||||
|
password=passwords['OVERCLOUD_NOVA_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('nova', 'computev3', 'http://127.0.0.3:8774',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:8774',
|
||||||
|
description='Nova Compute Service v3',
|
||||||
|
password=passwords['OVERCLOUD_NOVA_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
mock.call('swift', 'object-store', 'http://127.0.0.3:8080',
|
||||||
|
self.mock_identity,
|
||||||
|
internal_url='http://127.0.0.1:8080',
|
||||||
|
description='Swift Object Storage Service',
|
||||||
|
password=passwords['OVERCLOUD_SWIFT_PASSWORD'],
|
||||||
|
region='regionOne'),
|
||||||
|
# Tuskar not enabled yet
|
||||||
|
# mock.call('tuskar', 'management', 'https://127.0.0.2:8585',
|
||||||
|
# self.mock_identity,
|
||||||
|
# internal_url='http://127.0.0.1:8585',
|
||||||
|
# description='Tuskar Service',
|
||||||
|
# password=passwords['OVERCLOUD_TUSKAR_PASSWORD'],
|
||||||
|
# region='regionOne'),
|
||||||
|
mock.call('horizon', 'dashboard', 'http://127.0.0.1:',
|
||||||
|
self.mock_identity,
|
||||||
|
description='OpenStack Dashboard',
|
||||||
|
internal_url='http://127.0.0.1:',
|
||||||
|
region='regionOne')
|
||||||
|
])
|
||||||
|
|
||||||
|
@mock.patch('rdomanager_oscplugin.utils.register_endpoint')
|
||||||
|
def test_setup_endpoints_skip_no_password(self, mock_register_endpoint):
|
||||||
|
mock_register_endpoint.reset_mock()
|
||||||
|
|
||||||
|
passwords = dict((password, 'password') for password in (
|
||||||
|
"OVERCLOUD_GLANCE_PASSWORD",
|
||||||
|
"OVERCLOUD_HEAT_PASSWORD",
|
||||||
|
"OVERCLOUD_NEUTRON_PASSWORD",
|
||||||
|
"OVERCLOUD_NOVA_PASSWORD",
|
||||||
|
))
|
||||||
|
|
||||||
|
utils.setup_endpoints(
|
||||||
|
'127.0.0.1',
|
||||||
|
passwords,
|
||||||
|
self.mock_identity,
|
||||||
|
region='regionOne',
|
||||||
|
enable_horizon=True,
|
||||||
|
ssl='127.0.0.2'
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(mock_register_endpoint.call_count, 7)
|
||||||
|
@@ -27,6 +27,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
|||||||
# Get the command object to test
|
# Get the command object to test
|
||||||
self.cmd = overcloud_deploy.DeployOvercloud(self.app, None)
|
self.cmd = overcloud_deploy.DeployOvercloud(self.app, None)
|
||||||
|
|
||||||
|
@mock.patch('rdomanager_oscplugin.utils.setup_endpoints')
|
||||||
@mock.patch('time.sleep', return_value=None)
|
@mock.patch('time.sleep', return_value=None)
|
||||||
@mock.patch('os_cloud_config.keystone.initialize')
|
@mock.patch('os_cloud_config.keystone.initialize')
|
||||||
@mock.patch('rdomanager_oscplugin.utils.remove_known_hosts')
|
@mock.patch('rdomanager_oscplugin.utils.remove_known_hosts')
|
||||||
@@ -44,7 +45,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
|||||||
mock_get_templte_contents, mock_process_multiple_env,
|
mock_get_templte_contents, mock_process_multiple_env,
|
||||||
set_nodes_state_mock, wait_for_stack_ready_mock,
|
set_nodes_state_mock, wait_for_stack_ready_mock,
|
||||||
mock_remove_known_hosts, mock_keystone_initialize,
|
mock_remove_known_hosts, mock_keystone_initialize,
|
||||||
mock_sleep):
|
mock_sleep, mock_setup_endpoints):
|
||||||
|
|
||||||
arglist = ['--use-tripleo-heat-templates', ]
|
arglist = ['--use-tripleo-heat-templates', ]
|
||||||
verifylist = [
|
verifylist = [
|
||||||
|
@@ -24,6 +24,8 @@ import sys
|
|||||||
import time
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
from rdomanager_oscplugin import exceptions
|
||||||
|
|
||||||
|
|
||||||
def _generate_password():
|
def _generate_password():
|
||||||
"""Create a random password
|
"""Create a random password
|
||||||
@@ -327,5 +329,246 @@ def remove_known_hosts(overcloud_ip):
|
|||||||
subprocess.check_call(command)
|
subprocess.check_call(command)
|
||||||
|
|
||||||
|
|
||||||
def setup_endpoints(overcloud_ip, passwords):
|
def register_endpoint(name,
|
||||||
pass
|
endpoint_type,
|
||||||
|
public_url,
|
||||||
|
identity_client,
|
||||||
|
password=None,
|
||||||
|
description=None,
|
||||||
|
admin_url=None,
|
||||||
|
internal_url=None,
|
||||||
|
region="regionOne"):
|
||||||
|
SUFFIXES = {
|
||||||
|
'baremetal': {'suffix': '/'},
|
||||||
|
'compute': {'suffix': "/v2/$(tenant_id)s"},
|
||||||
|
'computev3': {'suffix': "/v3"},
|
||||||
|
'dashboard': {'suffix': "/",
|
||||||
|
'admin_suffix': "/admin"},
|
||||||
|
'ec2': {'suffix': '/services/Cloud',
|
||||||
|
'admin_suffix': '/service/Admin'},
|
||||||
|
'identity': {'suffix': "/v2.0"},
|
||||||
|
'image': {'suffix': '/'},
|
||||||
|
'management': {'suffix': "/v2"},
|
||||||
|
'metering': {'suffix': '/'},
|
||||||
|
'network': {'suffix': '/'},
|
||||||
|
'object-store': {'suffix': "/v1/AUTH_%%(tenant_id)s",
|
||||||
|
'admin_suffix': "/v1"},
|
||||||
|
'orchestration': {'suffix': "/v1/%%(tenant_id)s"},
|
||||||
|
'volume': {'suffix': "/v1/%%(tenant_id)s"},
|
||||||
|
'volumev2': {'suffix': "/v2/%%(tenant_id)s"},
|
||||||
|
}
|
||||||
|
|
||||||
|
service = SUFFIXES.get(endpoint_type)
|
||||||
|
|
||||||
|
if not service:
|
||||||
|
raise exceptions.UnknownService
|
||||||
|
|
||||||
|
suffix = service['suffix']
|
||||||
|
admin_suffix = service.get('admin_suffix', suffix)
|
||||||
|
|
||||||
|
if not internal_url:
|
||||||
|
internal_url = public_url
|
||||||
|
|
||||||
|
if not admin_url:
|
||||||
|
admin_url = internal_url
|
||||||
|
|
||||||
|
roles = identity_client.roles.list()
|
||||||
|
admin_role_id = next((role.id for role in roles if role.name in 'admin'),
|
||||||
|
None)
|
||||||
|
if not admin_role_id:
|
||||||
|
raise exceptions.NotFound
|
||||||
|
|
||||||
|
if endpoint_type not in 'dashboard':
|
||||||
|
projects = identity_client.projects.list()
|
||||||
|
service_project_id = next(project.id for project in
|
||||||
|
projects if project.name in 'service')
|
||||||
|
|
||||||
|
if not password:
|
||||||
|
password = _generate_password()
|
||||||
|
|
||||||
|
# Some services have multiple endpoints, the user doesn't need to
|
||||||
|
# be recreated
|
||||||
|
users = identity_client.users.list()
|
||||||
|
user_id = next((user.id for user in users if user.name in name), None)
|
||||||
|
if not user_id:
|
||||||
|
user = identity_client.users.create(
|
||||||
|
name=name,
|
||||||
|
domain=None,
|
||||||
|
default_project=service_project_id,
|
||||||
|
password=password,
|
||||||
|
email='nobody@example.com',
|
||||||
|
description=None,
|
||||||
|
enabled=True
|
||||||
|
)
|
||||||
|
user_id = user.id
|
||||||
|
role = identity_client.roles.list(
|
||||||
|
user=user_id,
|
||||||
|
project=service_project_id)
|
||||||
|
if not role:
|
||||||
|
# Log "Creating user-role assignment for user $NAME, role admin,
|
||||||
|
# tenant service"
|
||||||
|
identity_client.roles.grant(
|
||||||
|
admin_role_id,
|
||||||
|
user=user_id,
|
||||||
|
project=service_project_id
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add the admin tenant role for ceilometer user to enable polling
|
||||||
|
# services
|
||||||
|
if endpoint_type in 'metering':
|
||||||
|
admin_project_id = next(project.id for project in
|
||||||
|
projects if project.name in 'admin')
|
||||||
|
# Log "Creating user-role assignment for user $NAME, role admin,
|
||||||
|
# tenant admin"
|
||||||
|
role = identity_client.roles.list(
|
||||||
|
user=user_id,
|
||||||
|
project=admin_project_id
|
||||||
|
)
|
||||||
|
if not role:
|
||||||
|
identity_client.roles.grant(
|
||||||
|
admin_role_id,
|
||||||
|
user=user_id,
|
||||||
|
project=admin_project_id
|
||||||
|
)
|
||||||
|
|
||||||
|
# swift polling requires ResellerAdmin role to be added to the
|
||||||
|
# Ceilometer user
|
||||||
|
reseller_admin_role_id = next(role.id for role in roles if
|
||||||
|
role.name in 'ResellerAdmin')
|
||||||
|
identity_client.roles.grant(
|
||||||
|
reseller_admin_role_id,
|
||||||
|
user=user_id,
|
||||||
|
project=admin_project_id
|
||||||
|
)
|
||||||
|
|
||||||
|
service = identity_client.services.create(
|
||||||
|
name=name,
|
||||||
|
type=endpoint_type,
|
||||||
|
description=description,
|
||||||
|
enabled=True
|
||||||
|
)
|
||||||
|
# Assumes v2 identity_client
|
||||||
|
identity_client.endpoints.create(
|
||||||
|
region,
|
||||||
|
service.id,
|
||||||
|
"%s%s" % (public_url, suffix),
|
||||||
|
"%s%s" % (admin_url, admin_suffix),
|
||||||
|
"%s%s" % (internal_url, suffix)
|
||||||
|
)
|
||||||
|
# Log "Service $TYPE created"
|
||||||
|
|
||||||
|
|
||||||
|
def setup_endpoints(overcloud_ip,
|
||||||
|
passwords,
|
||||||
|
identity_client,
|
||||||
|
region='regionOne',
|
||||||
|
enable_horizon=False,
|
||||||
|
ssl=None,
|
||||||
|
public=None):
|
||||||
|
"""Perform initial setup of a cloud running on <overcloud_ip>
|
||||||
|
|
||||||
|
This will register ec2, image, orchestration, identity, network,
|
||||||
|
volume (optional), dashboard (optional), metering (optional) and
|
||||||
|
compute services as running on the default ports on controlplane-ip.
|
||||||
|
"""
|
||||||
|
|
||||||
|
SERVICE_LIST = [
|
||||||
|
{'name': 'ceilometer', 'type': 'metering',
|
||||||
|
'description': 'Ceilometer Service',
|
||||||
|
'port': 8777, 'ssl_port': 13777,
|
||||||
|
'password_field': 'OVERCLOUD_CEILOMETER_PASSWORD'},
|
||||||
|
{'name': 'cinder', 'type': 'volume',
|
||||||
|
'description': 'Cinder Volume Service',
|
||||||
|
'port': 8776, 'ssl_port': 13776,
|
||||||
|
'password_field': 'OVERCLOUD_CINDER_PASSWORD'},
|
||||||
|
{'name': 'cinderv2', 'type': 'volumev2',
|
||||||
|
'description': 'Cinder Volume Service V2',
|
||||||
|
'port': 8776, 'ssl_port': 13776,
|
||||||
|
'password_field': 'OVERCLOUD_CINDER_PASSWORD'},
|
||||||
|
{'name': 'ec2', 'type': 'ec2',
|
||||||
|
'description': 'EC2 Compatibility Layer',
|
||||||
|
'port': 8773, 'ssl_port': 13773},
|
||||||
|
{'name': 'glance', 'type': 'image',
|
||||||
|
'description': 'Glance Image Service',
|
||||||
|
'port': 9292, 'ssl_port': 13292,
|
||||||
|
'password_field': 'OVERCLOUD_GLANCE_PASSWORD'},
|
||||||
|
{'name': 'heat', 'type': 'orchestration',
|
||||||
|
'description': 'Heat Service',
|
||||||
|
'port': 8004, 'ssl_port': 13004,
|
||||||
|
'password_field': 'OVERCLOUD_HEAT_PASSWORD'},
|
||||||
|
{'name': 'ironic', 'type': 'baremetal',
|
||||||
|
'description': 'Ironic Service',
|
||||||
|
'port': 6385, 'ssl_port': 6385,
|
||||||
|
'password_field': 'OVERCLOUD_IRONIC_PASSWORD'},
|
||||||
|
{'name': 'neutron', 'type': 'network',
|
||||||
|
'description': 'Neutron Service',
|
||||||
|
'port': 9696, 'ssl_port': 13696,
|
||||||
|
'password_field': 'OVERCLOUD_NEUTRON_PASSWORD'},
|
||||||
|
{'name': 'nova', 'type': 'compute',
|
||||||
|
'description': 'Nova Compute Service',
|
||||||
|
'port': 8774, 'ssl_port': 13774,
|
||||||
|
'password_field': 'OVERCLOUD_NOVA_PASSWORD'},
|
||||||
|
{'name': 'nova', 'type': 'computev3',
|
||||||
|
'description': 'Nova Compute Service v3',
|
||||||
|
'port': 8774, 'ssl_port': 13774,
|
||||||
|
'password_field': 'OVERCLOUD_NOVA_PASSWORD'},
|
||||||
|
{'name': 'swift', 'type': 'object-store',
|
||||||
|
'description': 'Swift Object Storage Service',
|
||||||
|
'port': 8080, 'ssl_port': 13080,
|
||||||
|
'password_field': 'OVERCLOUD_SWIFT_PASSWORD'},
|
||||||
|
{'name': 'tuskar', 'type': 'management',
|
||||||
|
'description': 'Tuskar Service',
|
||||||
|
'port': 8585, 'ssl_port': 8585,
|
||||||
|
'password_field': 'OVERCLOUD_TUSKAR_PASSWORD'},
|
||||||
|
]
|
||||||
|
|
||||||
|
skip_no_password = [
|
||||||
|
'metering',
|
||||||
|
'volume',
|
||||||
|
'volumev2',
|
||||||
|
'object-store',
|
||||||
|
'baremetal',
|
||||||
|
'management'
|
||||||
|
]
|
||||||
|
|
||||||
|
internal_host = 'http://%s:' % overcloud_ip
|
||||||
|
|
||||||
|
if ssl:
|
||||||
|
public_host = "https://%s:" % ssl
|
||||||
|
elif public:
|
||||||
|
public_host = "http://%s:" % public
|
||||||
|
else:
|
||||||
|
public_host = internal_host
|
||||||
|
|
||||||
|
for service in SERVICE_LIST:
|
||||||
|
password_field = service.get('password_field', None)
|
||||||
|
password = passwords.get(password_field, None)
|
||||||
|
|
||||||
|
if not password and service['type'] in skip_no_password:
|
||||||
|
continue
|
||||||
|
|
||||||
|
port = service['port']
|
||||||
|
ssl_port = service['ssl_port'] if ssl else port
|
||||||
|
args = (
|
||||||
|
service['name'],
|
||||||
|
service['type'],
|
||||||
|
"%s%d" % (public_host, port),
|
||||||
|
identity_client,
|
||||||
|
)
|
||||||
|
kwargs = {
|
||||||
|
'description': service['description'],
|
||||||
|
'region': region,
|
||||||
|
'internal_url': "%s%d" % (internal_host, ssl_port),
|
||||||
|
}
|
||||||
|
|
||||||
|
if password:
|
||||||
|
kwargs.update({'password': password})
|
||||||
|
|
||||||
|
register_endpoint(*args, **kwargs)
|
||||||
|
|
||||||
|
if enable_horizon:
|
||||||
|
# Horizon is different enough to warrant a separate case
|
||||||
|
register_endpoint('horizon', 'dashboard', internal_host,
|
||||||
|
identity_client, description="OpenStack Dashboard",
|
||||||
|
internal_url=internal_host,
|
||||||
|
region=region)
|
||||||
|
@@ -265,7 +265,7 @@ class DeployOvercloud(command.Command):
|
|||||||
except ksc_exc.Conflict:
|
except ksc_exc.Conflict:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
utils.setup_endpoints(overcloud_ip, self.passwords)
|
utils.setup_endpoints(overcloud_ip, self.passwords, identity_client)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
identity_client.roles.create(name='heat_stack_user')
|
identity_client.roles.create(name='heat_stack_user')
|
||||||
|
Reference in New Issue
Block a user