Add overcloud deploy post config and add network initialization
Change-Id: Iabeb59043a90dc300dc95306f221f1ac8eb1ee6a
This commit is contained in:
parent
abbaad4412
commit
176bc90024
|
@ -13,13 +13,9 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
import mock
|
import mock
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
from rdomanager_oscplugin import exceptions
|
|
||||||
from rdomanager_oscplugin.tests.v1.utils import (
|
|
||||||
generate_overcloud_passwords_mock)
|
|
||||||
from rdomanager_oscplugin import utils
|
from rdomanager_oscplugin import utils
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,23 +54,25 @@ class TestPasswordsUtil(TestCase):
|
||||||
@mock.patch("rdomanager_oscplugin.utils._generate_password",
|
@mock.patch("rdomanager_oscplugin.utils._generate_password",
|
||||||
return_value="PASSWORD")
|
return_value="PASSWORD")
|
||||||
def test_load_passwords(self, generate_password_mock, isfile_mock):
|
def test_load_passwords(self, generate_password_mock, isfile_mock):
|
||||||
|
PASSWORDS = [
|
||||||
|
'OVERCLOUD_ADMIN_PASSWORD=PASSWORD\n',
|
||||||
|
'OVERCLOUD_ADMIN_TOKEN=PASSWORD\n',
|
||||||
|
'OVERCLOUD_CEILOMETER_PASSWORD=PASSWORD\n',
|
||||||
|
'OVERCLOUD_CEILOMETER_SECRET=PASSWORD\n',
|
||||||
|
'OVERCLOUD_CINDER_PASSWORD=PASSWORD\n',
|
||||||
|
'OVERCLOUD_DEMO_PASSWORD=PASSWORD\n',
|
||||||
|
'OVERCLOUD_GLANCE_PASSWORD=PASSWORD\n',
|
||||||
|
'OVERCLOUD_HEAT_PASSWORD=PASSWORD\n',
|
||||||
|
'OVERCLOUD_HEAT_STACK_DOMAIN_PASSWORD=PASSWORD\n',
|
||||||
|
'OVERCLOUD_NEUTRON_PASSWORD=PASSWORD\n',
|
||||||
|
'OVERCLOUD_NOVA_PASSWORD=PASSWORD\n',
|
||||||
|
'OVERCLOUD_SWIFT_HASH=PASSWORD\n',
|
||||||
|
'OVERCLOUD_SWIFT_PASSWORD=PASSWORD\n',
|
||||||
|
]
|
||||||
|
|
||||||
mock_open = mock.mock_open()
|
mock_open = mock.mock_open(read_data=''.join(PASSWORDS))
|
||||||
mock_open().__iter__.return_value = iter([
|
mock_open.return_value.__iter__ = lambda self: self
|
||||||
'OVERCLOUD_ADMIN_PASSWORD=PASSWORD',
|
mock_open.return_value.__next__ = lambda self: self.readline()
|
||||||
'OVERCLOUD_ADMIN_TOKEN=PASSWORD',
|
|
||||||
'OVERCLOUD_CEILOMETER_PASSWORD=PASSWORD',
|
|
||||||
'OVERCLOUD_CEILOMETER_SECRET=PASSWORD',
|
|
||||||
'OVERCLOUD_CINDER_PASSWORD=PASSWORD',
|
|
||||||
'OVERCLOUD_DEMO_PASSWORD=PASSWORD',
|
|
||||||
'OVERCLOUD_GLANCE_PASSWORD=PASSWORD',
|
|
||||||
'OVERCLOUD_HEAT_PASSWORD=PASSWORD',
|
|
||||||
'OVERCLOUD_HEAT_STACK_DOMAIN_PASSWORD=PASSWORD',
|
|
||||||
'OVERCLOUD_NEUTRON_PASSWORD=PASSWORD',
|
|
||||||
'OVERCLOUD_NOVA_PASSWORD=PASSWORD',
|
|
||||||
'OVERCLOUD_SWIFT_HASH=PASSWORD',
|
|
||||||
'OVERCLOUD_SWIFT_PASSWORD=PASSWORD',
|
|
||||||
])
|
|
||||||
|
|
||||||
with mock.patch('six.moves.builtins.open', mock_open):
|
with mock.patch('six.moves.builtins.open', mock_open):
|
||||||
passwords = utils.generate_overcloud_passwords()
|
passwords = utils.generate_overcloud_passwords()
|
||||||
|
@ -357,381 +355,3 @@ 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')
|
|
||||||
]
|
|
||||||
|
|
||||||
Role = namedtuple('Role', 'id name')
|
|
||||||
|
|
||||||
def _role_list_side_effect(*args, **kwargs):
|
|
||||||
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
|
|
||||||
|
|
||||||
self.mock_identity.roles.roles_for_user.return_value = (
|
|
||||||
Role(id='123', name='admin'))
|
|
||||||
|
|
||||||
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',
|
|
||||||
'dashboard',
|
|
||||||
'description'
|
|
||||||
)
|
|
||||||
|
|
||||||
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.roles_for_user.assert_has_calls(
|
|
||||||
[
|
|
||||||
mock.call('123', '123')
|
|
||||||
]
|
|
||||||
)
|
|
||||||
self.mock_identity.roles.list.assert_called_once_with()
|
|
||||||
|
|
||||||
self.mock_identity.services.create.assert_called_once_with(
|
|
||||||
'nova',
|
|
||||||
'compute',
|
|
||||||
'description'
|
|
||||||
)
|
|
||||||
|
|
||||||
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(
|
|
||||||
'ceilometer',
|
|
||||||
'password',
|
|
||||||
'nobody@example.com',
|
|
||||||
tenant_id='123',
|
|
||||||
enabled=True
|
|
||||||
)
|
|
||||||
self.mock_identity.services.create.assert_called_once_with(
|
|
||||||
'ceilometer',
|
|
||||||
'metering',
|
|
||||||
'description'
|
|
||||||
)
|
|
||||||
|
|
||||||
self.mock_identity.endpoints.create.assert_called_once_with(
|
|
||||||
'regionOne',
|
|
||||||
self.services_create_mock.id,
|
|
||||||
"url/",
|
|
||||||
"url/",
|
|
||||||
"url/"
|
|
||||||
)
|
|
||||||
|
|
||||||
self.mock_identity.roles.roles_for_user.assert_has_calls(
|
|
||||||
[
|
|
||||||
mock.call(self.users_create_mock.id, '123'),
|
|
||||||
mock.call(self.users_create_mock.id, '234')
|
|
||||||
]
|
|
||||||
)
|
|
||||||
self.mock_identity.roles.list.assert_called_once_with()
|
|
||||||
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 = generate_overcloud_passwords_mock()
|
|
||||||
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 = generate_overcloud_passwords_mock()
|
|
||||||
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)
|
|
||||||
|
|
|
@ -31,8 +31,12 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
||||||
|
|
||||||
self._get_passwords = generate_overcloud_passwords_mock
|
self._get_passwords = generate_overcloud_passwords_mock
|
||||||
|
|
||||||
|
@mock.patch('rdomanager_oscplugin.v1.overcloud_deploy.DeployOvercloud.'
|
||||||
|
'_update_nodesjson')
|
||||||
@mock.patch('rdomanager_oscplugin.utils.generate_overcloud_passwords')
|
@mock.patch('rdomanager_oscplugin.utils.generate_overcloud_passwords')
|
||||||
@mock.patch('rdomanager_oscplugin.utils.setup_endpoints')
|
@mock.patch('rdomanager_oscplugin.v1.overcloud_deploy.DeployOvercloud.'
|
||||||
|
'_create_overcloudrc')
|
||||||
|
@mock.patch('os_cloud_config.keystone.setup_endpoints', autospec=True)
|
||||||
@mock.patch('time.sleep', return_value=None)
|
@mock.patch('time.sleep', return_value=None)
|
||||||
@mock.patch('os_cloud_config.keystone.initialize', autospec=True)
|
@mock.patch('os_cloud_config.keystone.initialize', autospec=True)
|
||||||
@mock.patch('rdomanager_oscplugin.utils.remove_known_hosts', autospec=True)
|
@mock.patch('rdomanager_oscplugin.utils.remove_known_hosts', autospec=True)
|
||||||
|
@ -56,7 +60,9 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
||||||
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_setup_endpoints,
|
mock_sleep, mock_setup_endpoints,
|
||||||
mock_generate_overcloud_passwords):
|
mock_create_overcloudrc,
|
||||||
|
mock_generate_overcloud_passwords,
|
||||||
|
mock_update_nodesjson):
|
||||||
|
|
||||||
arglist = ['--use-tripleo-heat-templates', ]
|
arglist = ['--use-tripleo-heat-templates', ]
|
||||||
verifylist = [
|
verifylist = [
|
||||||
|
@ -106,6 +112,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
||||||
self.assertEqual(kwargs['environment'], 'env')
|
self.assertEqual(kwargs['environment'], 'env')
|
||||||
self.assertEqual(kwargs['stack_name'], 'overcloud')
|
self.assertEqual(kwargs['stack_name'], 'overcloud')
|
||||||
|
|
||||||
|
@mock.patch('rdomanager_oscplugin.v1.overcloud_deploy.DeployOvercloud.'
|
||||||
|
'_update_nodesjson')
|
||||||
@mock.patch('rdomanager_oscplugin.utils.get_config_value', autospec=True)
|
@mock.patch('rdomanager_oscplugin.utils.get_config_value', autospec=True)
|
||||||
@mock.patch('rdomanager_oscplugin.utils.generate_overcloud_passwords')
|
@mock.patch('rdomanager_oscplugin.utils.generate_overcloud_passwords')
|
||||||
@mock.patch('heatclient.common.template_utils.'
|
@mock.patch('heatclient.common.template_utils.'
|
||||||
|
@ -116,15 +124,15 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
||||||
@mock.patch('rdomanager_oscplugin.v1.overcloud_deploy.DeployOvercloud.'
|
@mock.patch('rdomanager_oscplugin.v1.overcloud_deploy.DeployOvercloud.'
|
||||||
'_pre_heat_deploy')
|
'_pre_heat_deploy')
|
||||||
@mock.patch('rdomanager_oscplugin.v1.overcloud_deploy.DeployOvercloud.'
|
@mock.patch('rdomanager_oscplugin.v1.overcloud_deploy.DeployOvercloud.'
|
||||||
'_post_heat_deploy')
|
'_create_overcloudrc')
|
||||||
@mock.patch('rdomanager_oscplugin.v1.overcloud_deploy.DeployOvercloud.'
|
@mock.patch('rdomanager_oscplugin.v1.overcloud_deploy.DeployOvercloud.'
|
||||||
'_heat_deploy')
|
'_heat_deploy')
|
||||||
def test_tuskar_deploy(self, mock_heat_deploy, mock_post_deploy,
|
def test_tuskar_deploy(self, mock_heat_deploy, mock_create_overcloudrc,
|
||||||
most_pre_deploy, mock_get_stack,
|
most_pre_deploy, mock_get_stack,
|
||||||
mock_get_templte_contents,
|
mock_get_templte_contents,
|
||||||
mock_process_multiple_env,
|
mock_process_multiple_env,
|
||||||
mock_generate_overcloud_passwords,
|
mock_generate_overcloud_passwords,
|
||||||
mock_get_key):
|
mock_get_key, mock_update_nodesjson):
|
||||||
|
|
||||||
arglist = ['--plan-uuid', 'UUID', '--output-dir', 'fake']
|
arglist = ['--plan-uuid', 'UUID', '--output-dir', 'fake']
|
||||||
verifylist = [
|
verifylist = [
|
||||||
|
|
|
@ -26,7 +26,18 @@ import sys
|
||||||
import time
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from rdomanager_oscplugin import exceptions
|
|
||||||
|
SERVICE_LIST = {
|
||||||
|
'ceilometer': {'password_field': 'OVERCLOUD_CEILOMETER_PASSWORD'},
|
||||||
|
'cinder': {'password_field': 'OVERCLOUD_CINDER_PASSWORD'},
|
||||||
|
'ec2': {},
|
||||||
|
'glance': {'password_field': 'OVERCLOUD_GLANCE_PASSWORD'},
|
||||||
|
'heat': {'password_field': 'OVERCLOUD_HEAT_PASSWORD'},
|
||||||
|
'neutron': {'password_field': 'OVERCLOUD_NEUTRON_PASSWORD'},
|
||||||
|
'nova': {'password_field': 'OVERCLOUD_NOVA_PASSWORD'},
|
||||||
|
'novav3': {'password_field': 'OVERCLOUD_NOVA_PASSWORD'},
|
||||||
|
'swift': {'password_field': 'OVERCLOUD_SWIFT_PASSWORD'},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def _generate_password():
|
def _generate_password():
|
||||||
|
@ -51,7 +62,7 @@ def generate_overcloud_passwords(output_file="tripleo-overcloud-passwords"):
|
||||||
|
|
||||||
if os.path.isfile(output_file):
|
if os.path.isfile(output_file):
|
||||||
with open(output_file) as f:
|
with open(output_file) as f:
|
||||||
return dict(line.split('=') for line in f)
|
return dict(line.split('=') for line in f.read().splitlines())
|
||||||
|
|
||||||
password_names = (
|
password_names = (
|
||||||
"OVERCLOUD_ADMIN_PASSWORD",
|
"OVERCLOUD_ADMIN_PASSWORD",
|
||||||
|
@ -354,245 +365,6 @@ def remove_known_hosts(overcloud_ip):
|
||||||
subprocess.check_call(command)
|
subprocess.check_call(command)
|
||||||
|
|
||||||
|
|
||||||
def register_endpoint(name,
|
|
||||||
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,
|
|
||||||
password,
|
|
||||||
'nobody@example.com',
|
|
||||||
tenant_id=service_project_id,
|
|
||||||
enabled=True
|
|
||||||
)
|
|
||||||
user_id = user.id
|
|
||||||
|
|
||||||
role = identity_client.roles.roles_for_user(
|
|
||||||
user_id, 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.roles_for_user(
|
|
||||||
user_id, 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,
|
|
||||||
endpoint_type,
|
|
||||||
description)
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
def create_cephx_key():
|
def create_cephx_key():
|
||||||
# NOTE(gfidente): Taken from
|
# NOTE(gfidente): Taken from
|
||||||
# https://github.com/ceph/ceph-deploy/blob/master/ceph_deploy/new.py#L21
|
# https://github.com/ceph/ceph-deploy/blob/master/ceph_deploy/new.py#L21
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import glob
|
import glob
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import six
|
import six
|
||||||
|
@ -25,9 +26,7 @@ import uuid
|
||||||
from cliff import command
|
from cliff import command
|
||||||
from heatclient.common import template_utils
|
from heatclient.common import template_utils
|
||||||
from heatclient.exc import HTTPNotFound
|
from heatclient.exc import HTTPNotFound
|
||||||
from keystoneclient import exceptions as ksc_exc
|
|
||||||
from openstackclient.i18n import _
|
from openstackclient.i18n import _
|
||||||
from os_cloud_config import keystone
|
|
||||||
from os_cloud_config import keystone_pki
|
from os_cloud_config import keystone_pki
|
||||||
|
|
||||||
from rdomanager_oscplugin import utils
|
from rdomanager_oscplugin import utils
|
||||||
|
@ -406,43 +405,45 @@ class DeployOvercloud(command.Command):
|
||||||
extra_envs = glob.glob(extra_dir + '/*/*environment*yaml')
|
extra_envs = glob.glob(extra_dir + '/*/*environment*yaml')
|
||||||
return extra_registries + extra_envs
|
return extra_registries + extra_envs
|
||||||
|
|
||||||
def _post_heat_deploy(self):
|
def _create_overcloudrc(self, stack, parsed_args):
|
||||||
"""Setup after the Heat stack create or update has been done."""
|
|
||||||
|
|
||||||
clients = self.app.client_manager
|
|
||||||
orchestration_client = clients.rdomanager_oscplugin.orchestration()
|
|
||||||
stack = self._get_stack(orchestration_client)
|
|
||||||
identity_client = self.app.client_manager.identity
|
|
||||||
|
|
||||||
overcloud_endpoint = self._get_overcloud_endpoint(stack)
|
overcloud_endpoint = self._get_overcloud_endpoint(stack)
|
||||||
overcloud_ip = six.moves.urllib.parse.urlparse(
|
overcloud_ip = six.moves.urllib.parse.urlparse(
|
||||||
overcloud_endpoint).hostname
|
overcloud_endpoint).hostname
|
||||||
utils.remove_known_hosts(overcloud_ip)
|
|
||||||
|
|
||||||
# TODO(dmatthews): Update os-cloud-config so that we don't need to
|
rc_params = {
|
||||||
# copy all the defaults from their CLI parser. They force us to pass
|
'NOVA_VERSION': '1.1',
|
||||||
# all values.
|
'COMPUTE_API_VERSION': '1.1',
|
||||||
keystone.initialize(
|
'OS_USERNAME': 'admin',
|
||||||
overcloud_ip, self.passwords['OVERCLOUD_ADMIN_TOKEN'],
|
'OS_TENANT_NAME': 'admin',
|
||||||
'admin.example.com', self.passwords['OVERCLOUD_ADMIN_PASSWORD'],
|
'OS_NO_CACHE': 'True',
|
||||||
'regionOne', None, None, 'heat-admin', 600, 10, True)
|
'OS_CLOUDNAME': 'overcloud',
|
||||||
|
'no_proxy': "%(no_proxy)s,%(overcloud_ip)s" % {
|
||||||
|
'no_proxy': parsed_args.no_proxy,
|
||||||
|
'overcloud_ip': overcloud_ip,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc_params.update({
|
||||||
|
'OS_PASSWORD': self.passwords['OVERCLOUD_ADMIN_PASSWORD'],
|
||||||
|
'OS_AUTH_URL': self._get_overcloud_endpoint(stack),
|
||||||
|
})
|
||||||
|
with open('overcloudrc', 'w') as f:
|
||||||
|
for key, value in rc_params.items():
|
||||||
|
f.write("export %(key)s=%(value)s\n" %
|
||||||
|
{'key': key, 'value': value})
|
||||||
|
|
||||||
try:
|
def _update_nodesjson(self, stack):
|
||||||
identity_client.roles.create(name='swiftoperator')
|
|
||||||
except ksc_exc.Conflict:
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
with open("instackenv.json") as f:
|
||||||
identity_client.roles.create(name='ResellerAdmin')
|
instack_env = json.load(f)
|
||||||
except ksc_exc.Conflict:
|
|
||||||
pass
|
|
||||||
|
|
||||||
utils.setup_endpoints(overcloud_ip, self.passwords, identity_client)
|
instack_env.setdefault('overcloud', {})
|
||||||
|
instack_env['overcloud']['password'] = (
|
||||||
|
self.passwords['OVERCLOUD_ADMIN_PASSWORD'])
|
||||||
|
instack_env['overcloud']['endpoint'] = (
|
||||||
|
self._get_overcloud_endpoint(stack))
|
||||||
|
|
||||||
try:
|
with open("instackenv.json", "w") as f:
|
||||||
identity_client.roles.create(name='heat_stack_user')
|
json.dump(instack_env, f)
|
||||||
except ksc_exc.Conflict:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def get_parser(self, prog_name):
|
def get_parser(self, prog_name):
|
||||||
parser = super(DeployOvercloud, self).get_parser(prog_name)
|
parser = super(DeployOvercloud, self).get_parser(prog_name)
|
||||||
|
@ -465,6 +466,18 @@ class DeployOvercloud(command.Command):
|
||||||
|
|
||||||
parser.add_argument('--libvirt-type', default='qemu')
|
parser.add_argument('--libvirt-type', default='qemu')
|
||||||
parser.add_argument('--ntp-server', default='')
|
parser.add_argument('--ntp-server', default='')
|
||||||
|
parser.add_argument(
|
||||||
|
'--tripleo-root',
|
||||||
|
default=os.environ.get('TRIPLEO_ROOT', '/etc/tripleo')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--nodes-json',
|
||||||
|
default=os.environ.get('NODES_JSON', 'instackenv.json')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--no-proxy',
|
||||||
|
default=os.environ.get('no_proxy', '')
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--plan-uuid',
|
'--plan-uuid',
|
||||||
help=_("The UUID of the Tuskar plan to deploy.")
|
help=_("The UUID of the Tuskar plan to deploy.")
|
||||||
|
@ -499,4 +512,12 @@ class DeployOvercloud(command.Command):
|
||||||
else:
|
else:
|
||||||
self._deploy_tuskar(stack, parsed_args)
|
self._deploy_tuskar(stack, parsed_args)
|
||||||
|
|
||||||
self._post_heat_deploy()
|
# Get a new copy of the stack after stack update/create. If it was a
|
||||||
|
# create then the previous stack object would be None.
|
||||||
|
stack = self._get_stack(orchestration_client)
|
||||||
|
|
||||||
|
self._create_overcloudrc(stack, parsed_args)
|
||||||
|
|
||||||
|
self._update_nodesjson(stack)
|
||||||
|
|
||||||
|
print("Overcloud Deployed")
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
# Copyright 2015 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import six
|
||||||
|
|
||||||
|
from cliff import command
|
||||||
|
from openstackclient.i18n import _
|
||||||
|
from os_cloud_config import keystone
|
||||||
|
from os_cloud_config import neutron
|
||||||
|
from os_cloud_config.utils import clients
|
||||||
|
|
||||||
|
from rdomanager_oscplugin import utils
|
||||||
|
|
||||||
|
|
||||||
|
class PostconfigOvercloud(command.Command):
|
||||||
|
"""Complete the configuration of the overcloud"""
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + ".PostconfigOvercloud")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(PostconfigOvercloud, self).get_parser(prog_name)
|
||||||
|
|
||||||
|
parser.add_argument('--overcloud_nameserver', default='8.8.8.8')
|
||||||
|
parser.add_argument('--floating-id-cidr', default='192.0.2.0/24')
|
||||||
|
parser.add_argument('--floating-ip-start', default='192.0.2.45')
|
||||||
|
parser.add_argument('--floating-ip-end', default='192.0.2.64')
|
||||||
|
parser.add_argument('--ibm-network-gateway', default='192.0.2.1')
|
||||||
|
parser.add_argument('--network-cidr', default='10.0.0.0/8')
|
||||||
|
parser.add_argument(
|
||||||
|
'overcloud_ip',
|
||||||
|
help=_('The IP address of the Overcloud endpoint')
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug("take_action(%s)" % parsed_args)
|
||||||
|
|
||||||
|
passwords = utils.generate_overcloud_passwords()
|
||||||
|
|
||||||
|
utils.remove_known_hosts(parsed_args.overcloud_ip)
|
||||||
|
|
||||||
|
keystone.initialize(
|
||||||
|
parsed_args.overcloud_ip,
|
||||||
|
passwords['OVERCLOUD_ADMIN_TOKEN'],
|
||||||
|
'admin@example.com',
|
||||||
|
passwords['OVERCLOUD_ADMIN_PASSWORD'],
|
||||||
|
user='heat-admin')
|
||||||
|
|
||||||
|
services = {}
|
||||||
|
for service, data in six.iteritems(utils.SERVICE_LIST):
|
||||||
|
service_data = {}
|
||||||
|
password_field = data.get('password_field')
|
||||||
|
if password_field:
|
||||||
|
service_data['password'] = passwords[password_field]
|
||||||
|
services.update({service: service_data})
|
||||||
|
|
||||||
|
identity_client = self.app.client_manager.identity
|
||||||
|
keystone.setup_endpoints(
|
||||||
|
services,
|
||||||
|
client=identity_client,
|
||||||
|
os_auth_url=self.app.client_manager.auth_ref.auth_url[0])
|
||||||
|
|
||||||
|
network_description = {
|
||||||
|
"float": {
|
||||||
|
"cidr": parsed_args.network_cidr,
|
||||||
|
"name": "default-net",
|
||||||
|
"nameserver": parsed_args.overcloud_nameserver
|
||||||
|
},
|
||||||
|
"external": {
|
||||||
|
"name": "ext-net",
|
||||||
|
"cidr": parsed_args.floating_id_cidr,
|
||||||
|
"allocation_start": parsed_args.floating_ip_start,
|
||||||
|
"allocation_end": parsed_args.floating_ip_end,
|
||||||
|
"gateway": parsed_args.ibm_network_gateway,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# retrieve needed Overcloud clients
|
||||||
|
auth_ref = self.app.client_manager.auth_ref
|
||||||
|
keystone_client = clients.get_keystone_client(
|
||||||
|
auth_ref.username,
|
||||||
|
passwords['OVERCLOUD_ADMIN_PASSWORD'],
|
||||||
|
auth_ref.project_name,
|
||||||
|
auth_ref.auth_url[0])
|
||||||
|
neutron_client = clients.get_neutron_client(
|
||||||
|
auth_ref.username,
|
||||||
|
passwords['OVERCLOUD_ADMIN_PASSWORD'],
|
||||||
|
auth_ref.project_name,
|
||||||
|
auth_ref.auth_url[0])
|
||||||
|
neutron.initialize_neutron(
|
||||||
|
network_description,
|
||||||
|
neutron_client=neutron_client,
|
||||||
|
keystone_client=keystone_client,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.app.client_manager.compute.flavors.create(
|
||||||
|
'm1.demo', 512, 1, 10, 'auto')
|
|
@ -64,6 +64,7 @@ openstack.rdomanager_oscplugin.v1 =
|
||||||
overcloud_image_build = rdomanager_oscplugin.v1.overcloud_image:BuildOvercloudImage
|
overcloud_image_build = rdomanager_oscplugin.v1.overcloud_image:BuildOvercloudImage
|
||||||
overcloud_image_upload = rdomanager_oscplugin.v1.overcloud_image:UploadOvercloudImage
|
overcloud_image_upload = rdomanager_oscplugin.v1.overcloud_image:UploadOvercloudImage
|
||||||
overcloud_node_delete = rdomanager_oscplugin.v1.overcloud_node:DeleteNode
|
overcloud_node_delete = rdomanager_oscplugin.v1.overcloud_node:DeleteNode
|
||||||
|
overcloud_postconfig = rdomanager_oscplugin.v1.overcloud_postconfig:PostconfigOvercloud
|
||||||
overcloud_scale_stack = rdomanager_oscplugin.v1.overcloud_scale:ScaleOvercloud
|
overcloud_scale_stack = rdomanager_oscplugin.v1.overcloud_scale:ScaleOvercloud
|
||||||
overcloud_update_stack = rdomanager_oscplugin.v1.overcloud_update:UpdateOvercloud
|
overcloud_update_stack = rdomanager_oscplugin.v1.overcloud_update:UpdateOvercloud
|
||||||
undercloud_install = rdomanager_oscplugin.v1.undercloud:InstallPlugin
|
undercloud_install = rdomanager_oscplugin.v1.undercloud:InstallPlugin
|
||||||
|
|
Loading…
Reference in New Issue