Browse Source

Support trustee_domain_name in config file

To setup magnum easier, name based configuration is important.
This patch makes config file support trustee_domain_name and
trustee_domain_admin_name in trust section.
If name and id of trustee domain are provided by user, both
values are passed through into keystone.

Closes-Bug: #1581372
Change-Id: Ia691aca7c29a471f6ba36a1a371ec1edf830b365
changes/91/322691/8
OTSUKA, Yuanying 5 years ago
parent
commit
1d74849193
10 changed files with 136 additions and 47 deletions
  1. +2
    -2
      devstack/lib/magnum
  2. +2
    -2
      doc/source/dev/manual-devstack.rst
  3. +61
    -6
      magnum/common/keystone.py
  4. +1
    -6
      magnum/conductor/handlers/common/trust_manager.py
  5. +14
    -6
      magnum/conductor/template_definition.py
  6. +37
    -0
      magnum/tests/unit/common/test_keystone.py
  7. +0
    -5
      magnum/tests/unit/conductor/handlers/common/test_trust_manager.py
  8. +8
    -8
      magnum/tests/unit/conductor/handlers/test_k8s_bay_conductor.py
  9. +5
    -6
      magnum/tests/unit/conductor/handlers/test_mesos_bay_conductor.py
  10. +6
    -6
      magnum/tests/unit/conductor/handlers/test_swarm_bay_conductor.py

+ 2
- 2
devstack/lib/magnum View File

@ -216,8 +216,8 @@ function create_magnum_conf {
--os-identity-api-version 3 role add \
--user $trustee_domain_admin_id --domain $trustee_domain_id \
admin
iniset $MAGNUM_CONF trust trustee_domain_id $trustee_domain_id
iniset $MAGNUM_CONF trust trustee_domain_admin_id $trustee_domain_admin_id
iniset $MAGNUM_CONF trust trustee_domain_name magnum
iniset $MAGNUM_CONF trust trustee_domain_admin_name trustee_domain_admin
iniset $MAGNUM_CONF trust trustee_domain_admin_password $MAGNUM_TRUSTEE_DOMAIN_ADMIN_PASSWORD
iniset $MAGNUM_CONF cinder_client region_name $REGION_NAME


+ 2
- 2
doc/source/dev/manual-devstack.rst View File

@ -206,11 +206,11 @@ Configure magnum::
/etc/magnum/magnum.conf
# set trustee domain id
sudo sed -i "s/#trustee_domain_id\s*=.*/trustee_domain_id=${TRUSTEE_DOMAIN_ID}/" \
sudo sed -i "s/#trustee_domain_name\s*=.*/trustee_domain_name=magnum/" \
/etc/magnum/magnum.conf
# set trustee domain admin id
sudo sed -i "s/#trustee_domain_admin_id\s*=.*/trustee_domain_admin_id=${TRUSTEE_DOMAIN_ADMIN_ID}/" \
sudo sed -i "s/#trustee_domain_admin_name\s*=.*/trustee_domain_admin_name=trustee_domain_admin/" \
/etc/magnum/magnum.conf
# set trustee domain admin password


+ 61
- 6
magnum/common/keystone.py View File

@ -33,9 +33,20 @@ LOG = logging.getLogger(__name__)
trust_opts = [
cfg.StrOpt('trustee_domain_id',
help=_('Id of the domain to create trustee for bays')),
cfg.StrOpt('trustee_domain_name',
help=_('Name of the domain to create trustee for bays')),
cfg.StrOpt('trustee_domain_admin_id',
help=_('Id of the admin with roles sufficient to manage users'
' in the trustee_domain')),
cfg.StrOpt('trustee_domain_admin_name',
help=_('Name of the admin with roles sufficient to manage users'
' in the trustee_domain')),
cfg.StrOpt('trustee_domain_admin_domain_id',
help=_('Id of the domain admin user\'s domain.'
' trustee_domain_id is used by default')),
cfg.StrOpt('trustee_domain_admin_domain_name',
help=_('Name of the domain admin user\'s domain.'
' trustee_domain_name is used by default')),
cfg.StrOpt('trustee_domain_admin_password', secret=True,
help=_('Password of trustee_domain_admin')),
cfg.ListOpt('roles',
@ -71,7 +82,10 @@ class KeystoneClientV3(object):
def __init__(self, context):
self.context = context
self._client = None
self._domain_admin_auth = None
self._domain_admin_session = None
self._domain_admin_client = None
self._trustee_domain_id = None
self._session = None
@property
@ -151,22 +165,62 @@ class KeystoneClientV3(object):
return client
@property
def domain_admin_client(self):
if not self._domain_admin_client:
auth = ka_v3.Password(
def domain_admin_auth(self):
user_domain_id = (
CONF.trust.trustee_domain_admin_domain_id or
CONF.trust.trustee_domain_id
)
user_domain_name = (
CONF.trust.trustee_domain_admin_domain_name or
CONF.trust.trustee_domain_name
)
if not self._domain_admin_auth:
self._domain_admin_auth = ka_v3.Password(
auth_url=self.auth_url,
user_id=CONF.trust.trustee_domain_admin_id,
username=CONF.trust.trustee_domain_admin_name,
user_domain_id=user_domain_id,
user_domain_name=user_domain_name,
domain_id=CONF.trust.trustee_domain_id,
domain_name=CONF.trust.trustee_domain_name,
password=CONF.trust.trustee_domain_admin_password)
return self._domain_admin_auth
@property
def domain_admin_session(self):
if not self._domain_admin_session:
session = ka_loading.session.Session().load_from_options(
auth=auth,
auth=self.domain_admin_auth,
insecure=CONF[CFG_LEGACY_GROUP].insecure,
cacert=CONF[CFG_LEGACY_GROUP].cafile,
key=CONF[CFG_LEGACY_GROUP].keyfile,
cert=CONF[CFG_LEGACY_GROUP].certfile)
self._domain_admin_client = kc_v3.Client(session=session)
self._domain_admin_session = session
return self._domain_admin_session
@property
def domain_admin_client(self):
if not self._domain_admin_client:
self._domain_admin_client = kc_v3.Client(
session=self.domain_admin_session
)
return self._domain_admin_client
@property
def trustee_domain_id(self):
if not self._trustee_domain_id:
try:
access = self.domain_admin_auth.get_access(
self.domain_admin_session
)
except kc_exception.Unauthorized:
LOG.error(_LE("Keystone client authentication failed"))
raise exception.AuthorizationFailure()
self._trustee_domain_id = access.domain_id
return self._trustee_domain_id
def create_trust(self, trustee_user):
trustor_user_id = self.session.get_user_id()
trustor_project_id = self.session.get_project_id()
@ -221,7 +275,8 @@ class KeystoneClientV3(object):
LOG.exception(_LE('Failed to delete trust'))
raise exception.TrustDeleteFailed(trust_id=bay.trust_id)
def create_trustee(self, username, password, domain_id):
def create_trustee(self, username, password):
domain_id = self.trustee_domain_id
try:
user = self.domain_admin_client.users.create(
name=username,


+ 1
- 6
magnum/conductor/handlers/common/trust_manager.py View File

@ -10,17 +10,12 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_config import cfg
from oslo_log import log as logging
from magnum.common import exception
from magnum.common import utils
from magnum.i18n import _LE
CONF = cfg.CONF
CONF.import_opt('trustee_domain_id', 'magnum.common.keystone',
group='trust')
LOG = logging.getLogger(__name__)
@ -30,7 +25,7 @@ def create_trustee_and_trust(osc, bay):
trustee = osc.keystone().create_trustee(
bay.uuid,
password,
CONF.trust.trustee_domain_id)
)
bay.trustee_username = trustee.name
bay.trustee_user_id = trustee.id
bay.trustee_password = password


+ 14
- 6
magnum/conductor/template_definition.py View File

@ -76,7 +76,6 @@ docker_registry_opts = [
CONF = cfg.CONF
CONF.register_opts(template_def_opts, group='bay')
CONF.register_opts(docker_registry_opts, group='docker_registry')
CONF.import_opt('trustee_domain_id', 'magnum.common.keystone', group='trust')
class ParameterMapping(object):
@ -339,6 +338,8 @@ class TemplateDefinition(object):
class BaseTemplateDefinition(TemplateDefinition):
def __init__(self):
super(BaseTemplateDefinition, self).__init__()
self._osc = None
self.add_parameter('ssh_key_name',
baymodel_attr='keypair_id',
required=True)
@ -359,9 +360,16 @@ class BaseTemplateDefinition(TemplateDefinition):
def template_path(self):
pass
def get_osc(self, context):
if not self._osc:
self._osc = clients.OpenStackClients(context)
return self._osc
def get_params(self, context, baymodel, bay, **kwargs):
osc = self.get_osc(context)
extra_params = kwargs.pop('extra_params', {})
extra_params['trustee_domain_id'] = CONF.trust.trustee_domain_id
extra_params['trustee_domain_id'] = osc.keystone().trustee_domain_id
extra_params['trustee_user_id'] = bay.trustee_user_id
extra_params['trustee_username'] = bay.trustee_username
extra_params['trustee_password'] = bay.trustee_password
@ -484,7 +492,7 @@ class K8sTemplateDefinition(BaseTemplateDefinition):
scale_mgr.get_removal_nodes(hosts))
extra_params['discovery_url'] = self.get_discovery_url(bay)
osc = clients.OpenStackClients(context)
osc = self.get_osc(context)
extra_params['magnum_url'] = osc.magnum_url()
if baymodel.tls_disabled:
@ -526,7 +534,7 @@ class AtomicK8sTemplateDefinition(K8sTemplateDefinition):
extra_params['username'] = context.user_name
extra_params['tenant_name'] = context.tenant
osc = clients.OpenStackClients(context)
osc = self.get_osc(context)
extra_params['region_name'] = osc.cinder_region_name()
return super(AtomicK8sTemplateDefinition,
@ -601,7 +609,7 @@ class AtomicSwarmTemplateDefinition(BaseTemplateDefinition):
# HACK(apmelton) - This uses the user's bearer token, ideally
# it should be replaced with an actual trust token with only
# access to do what the template needs it to do.
osc = clients.OpenStackClients(context)
osc = self.get_osc(context)
extra_params['magnum_url'] = osc.magnum_url()
label_list = ['flannel_network_cidr', 'flannel_backend',
@ -664,7 +672,7 @@ class UbuntuMesosTemplateDefinition(BaseTemplateDefinition):
# HACK(apmelton) - This uses the user's bearer token, ideally
# it should be replaced with an actual trust token with only
# access to do what the template needs it to do.
osc = clients.OpenStackClients(context)
osc = self.get_osc(context)
extra_params['auth_url'] = context.auth_url
extra_params['username'] = context.user_name
extra_params['tenant_name'] = context.tenant


+ 37
- 0
magnum/tests/unit/common/test_keystone.py View File

@ -156,6 +156,43 @@ class KeystoneClientTest(base.TestCase):
trustee_user='888888', role_names=['role3'],
impersonation=True)
@mock.patch('magnum.common.keystone.KeystoneClientV3.trustee_domain_id')
def test_create_trustee(self, mock_tdi, mock_ks):
expected_username = '_username'
expected_password = '_password'
expected_domain = '_expected_trustee_domain_id'
mock_tdi.__get__ = mock.MagicMock(return_value=expected_domain)
ks_client = keystone.KeystoneClientV3(self.ctx)
ks_client.create_trustee(
username=expected_username,
password=expected_password,
)
mock_ks.return_value.users.create.assert_called_once_with(
name=expected_username,
password=expected_password,
domain=expected_domain,
)
@mock.patch('magnum.common.keystone.KeystoneClientV3.domain_admin_auth')
@mock.patch('magnum.common.keystone.KeystoneClientV3.domain_admin_session')
def test_trustee_domain_id(self, mock_session, mock_auth, mock_ks):
expected_domain_id = '_expected_domain_id'
_mock_session = mock.MagicMock()
mock_session.__get__ = mock.MagicMock(return_value=_mock_session)
_mock_auth = mock.MagicMock()
mock_auth.__get__ = mock.MagicMock(return_value=_mock_auth)
mock_access = mock.MagicMock()
mock_access.domain_id = expected_domain_id
_mock_auth.get_access.return_value = mock_access
ks_client = keystone.KeystoneClientV3(self.ctx)
self.assertEqual(expected_domain_id, ks_client.trustee_domain_id)
_mock_auth.get_access.assert_called_once_with(
_mock_session
)
def test_get_validate_region_name(self, mock_ks):
key = 'region_name'
val = 'RegionOne'


+ 0
- 5
magnum/tests/unit/conductor/handlers/common/test_trust_manager.py View File

@ -14,7 +14,6 @@
import mock
from mock import patch
from oslo_config import fixture
from magnum.common import exception
from magnum.conductor.handlers.common import trust_manager
@ -35,7 +34,6 @@ class TrustManagerTestCase(base.BaseTestCase):
@patch('magnum.common.utils.generate_password')
def test_create_trustee_and_trust(self, mock_generate_password):
mock_password = "password_mock"
mock_trustee_domain_id = 'trustee_domain_id_mock'
mock_generate_password.return_value = mock_password
mock_bay = mock.MagicMock()
mock_bay.uuid = 'mock_bay_uuid'
@ -47,8 +45,6 @@ class TrustManagerTestCase(base.BaseTestCase):
mock_trust.id = 'mock_trust_id'
self.osc.keystone.return_value = mock_keystone
fixture.Config().config(group='trust',
trustee_domain_id=mock_trustee_domain_id)
mock_keystone.create_trustee.return_value = mock_trustee
mock_keystone.create_trust.return_value = mock_trust
@ -58,7 +54,6 @@ class TrustManagerTestCase(base.BaseTestCase):
mock_keystone.create_trustee.assert_called_once_with(
mock_bay.uuid,
mock_password,
mock_trustee_domain_id,
)
mock_keystone.create_trust.assert_called_once_with(
mock_trustee.id,


+ 8
- 8
magnum/tests/unit/conductor/handlers/test_k8s_bay_conductor.py View File

@ -65,9 +65,6 @@ class TestBayConductorWithK8s(base.TestCase):
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
}
cfg.CONF.set_override('trustee_domain_id',
'3527620c-b220-4f37-9ebc-6e63a81a9b2f',
group='trust')
self.context.auth_url = 'http://192.168.10.10:5000/v3'
self.context.user_name = 'fake_user'
self.context.tenant = 'fake_tenant'
@ -77,6 +74,9 @@ class TestBayConductorWithK8s(base.TestCase):
self.mock_osc = mock.MagicMock()
self.mock_osc.magnum_url.return_value = 'http://127.0.0.1:9511/v1'
self.mock_osc.cinder_region_name.return_value = 'RegionOne'
self.mock_keystone = mock.MagicMock()
self.mock_keystone.trustee_domain_id = 'trustee_domain_id'
self.mock_osc.keystone.return_value = self.mock_keystone
self.mock_osc_class.return_value = self.mock_osc
@patch('magnum.objects.BayModel.get_by_uuid')
@ -150,7 +150,7 @@ class TestBayConductorWithK8s(base.TestCase):
'region_name': self.mock_osc.cinder_region_name.return_value,
'tls_disabled': False,
'registry_enabled': False,
'trustee_domain_id': '3527620c-b220-4f37-9ebc-6e63a81a9b2f',
'trustee_domain_id': self.mock_keystone.trustee_domain_id,
'trustee_username': 'fake_trustee',
'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
@ -207,7 +207,7 @@ class TestBayConductorWithK8s(base.TestCase):
'tenant_name': 'fake_tenant',
'tls_disabled': False,
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'trustee_domain_id': '3527620c-b220-4f37-9ebc-6e63a81a9b2f',
'trustee_domain_id': self.mock_keystone.trustee_domain_id,
'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
'trustee_username': 'fake_trustee',
@ -250,7 +250,7 @@ class TestBayConductorWithK8s(base.TestCase):
'flannel_backend': 'vxlan',
'tls_disabled': False,
'registry_enabled': False,
'trustee_domain_id': '3527620c-b220-4f37-9ebc-6e63a81a9b2f',
'trustee_domain_id': self.mock_keystone.trustee_domain_id,
'trustee_username': 'fake_trustee',
'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
@ -299,7 +299,7 @@ class TestBayConductorWithK8s(base.TestCase):
'flannel_backend': 'vxlan',
'tls_disabled': False,
'registry_enabled': False,
'trustee_domain_id': '3527620c-b220-4f37-9ebc-6e63a81a9b2f',
'trustee_domain_id': self.mock_keystone.trustee_domain_id,
'trustee_username': 'fake_trustee',
'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
@ -422,7 +422,7 @@ class TestBayConductorWithK8s(base.TestCase):
'region_name': self.mock_osc.cinder_region_name.return_value,
'tls_disabled': False,
'registry_enabled': False,
'trustee_domain_id': '3527620c-b220-4f37-9ebc-6e63a81a9b2f',
'trustee_domain_id': self.mock_keystone.trustee_domain_id,
'trustee_username': 'fake_trustee',
'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',


+ 5
- 6
magnum/tests/unit/conductor/handlers/test_mesos_bay_conductor.py View File

@ -14,7 +14,6 @@
import mock
from mock import patch
from oslo_config import cfg
from oslo_service import loopingcall
from magnum.conductor.handlers import bay_conductor
@ -63,9 +62,6 @@ class TestBayConductorWithMesos(base.TestCase):
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
}
cfg.CONF.set_override('trustee_domain_id',
'3527620c-b220-4f37-9ebc-6e63a81a9b2f',
group='trust')
self.context.auth_url = 'http://192.168.10.10:5000/v3'
self.context.user_name = 'mesos_user'
self.context.tenant = 'admin'
@ -75,6 +71,9 @@ class TestBayConductorWithMesos(base.TestCase):
self.addCleanup(osc_patcher.stop)
self.mock_osc = mock.MagicMock()
self.mock_osc.cinder_region_name.return_value = 'RegionOne'
self.mock_keystone = mock.MagicMock()
self.mock_keystone.trustee_domain_id = 'trustee_domain_id'
self.mock_osc.keystone.return_value = self.mock_keystone
self.mock_osc_class.return_value = self.mock_osc
@patch('magnum.objects.BayModel.get_by_uuid')
@ -102,7 +101,7 @@ class TestBayConductorWithMesos(base.TestCase):
'https_proxy': 'https_proxy',
'no_proxy': 'no_proxy',
'cluster_name': 'bay1',
'trustee_domain_id': '3527620c-b220-4f37-9ebc-6e63a81a9b2f',
'trustee_domain_id': self.mock_keystone.trustee_domain_id,
'trustee_username': 'fake_trustee',
'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
@ -145,7 +144,7 @@ class TestBayConductorWithMesos(base.TestCase):
'number_of_slaves': 1,
'number_of_masters': 1,
'cluster_name': 'bay1',
'trustee_domain_id': '3527620c-b220-4f37-9ebc-6e63a81a9b2f',
'trustee_domain_id': self.mock_keystone.trustee_domain_id,
'trustee_username': 'fake_trustee',
'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',


+ 6
- 6
magnum/tests/unit/conductor/handlers/test_swarm_bay_conductor.py View File

@ -63,14 +63,14 @@ class TestBayConductorWithSwarm(base.TestCase):
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de'
}
cfg.CONF.set_override('trustee_domain_id',
'3527620c-b220-4f37-9ebc-6e63a81a9b2f',
group='trust')
osc_patcher = mock.patch('magnum.common.clients.OpenStackClients')
self.mock_osc_class = osc_patcher.start()
self.addCleanup(osc_patcher.stop)
self.mock_osc = mock.MagicMock()
self.mock_osc.magnum_url.return_value = 'http://127.0.0.1:9511/v1'
self.mock_keystone = mock.MagicMock()
self.mock_keystone.trustee_domain_id = 'trustee_domain_id'
self.mock_osc.keystone.return_value = self.mock_keystone
self.mock_osc_class.return_value = self.mock_osc
self.context.auth_url = 'http://192.168.10.10:5000/v3'
@ -108,7 +108,7 @@ class TestBayConductorWithSwarm(base.TestCase):
'flannel_network_cidr': '10.101.0.0/16',
'flannel_network_subnetlen': '26',
'flannel_backend': 'vxlan',
'trustee_domain_id': '3527620c-b220-4f37-9ebc-6e63a81a9b2f',
'trustee_domain_id': self.mock_keystone.trustee_domain_id,
'trustee_username': 'fake_trustee',
'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
@ -158,7 +158,7 @@ class TestBayConductorWithSwarm(base.TestCase):
'flannel_network_cidr': '10.101.0.0/16',
'flannel_network_subnetlen': '26',
'flannel_backend': 'vxlan',
'trustee_domain_id': '3527620c-b220-4f37-9ebc-6e63a81a9b2f',
'trustee_domain_id': self.mock_keystone.trustee_domain_id,
'trustee_username': 'fake_trustee',
'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
@ -201,7 +201,7 @@ class TestBayConductorWithSwarm(base.TestCase):
'flannel_network_cidr': u'10.101.0.0/16',
'flannel_network_subnetlen': u'26',
'flannel_backend': u'vxlan',
'trustee_domain_id': '3527620c-b220-4f37-9ebc-6e63a81a9b2f',
'trustee_domain_id': self.mock_keystone.trustee_domain_id,
'trustee_username': 'fake_trustee',
'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',


Loading…
Cancel
Save