Change references of tenant to project

Refernces from tenant to project were made in several
places, including DB, HTTP Headers, configuration items,
json in responses and devstack integration. Additionally,
a migration script using Alembic was included.

Implements: blueprint tenant-to-project-ref
Change-Id: I4b21182f555ccd412a4ca4e0ce753f07edcd07f8
This commit is contained in:
Cristian A Sanchez 2014-03-10 10:57:11 -03:00
parent 9552fce675
commit 6b26ecaf75
39 changed files with 189 additions and 117 deletions

View File

@ -29,10 +29,10 @@ def ctx_from_headers(headers):
return context.ClimateContext(
user_id=headers['X-User-Id'],
tenant_id=headers['X-Tenant-Id'],
project_id=headers['X-Project-Id'],
auth_token=headers['X-Auth-Token'],
service_catalog=service_catalog,
user_name=headers['X-User-Name'],
tenant_name=headers['X-Tenant-Name'],
project_name=headers['X-Project-Name'],
roles=map(unicode.strip, headers['X-Roles'].split(',')),
)

View File

@ -36,7 +36,7 @@ CONF.import_opt('os_auth_port', 'climate.config')
CONF.import_opt('os_auth_protocol', 'climate.config')
CONF.import_opt('os_admin_username', 'climate.config')
CONF.import_opt('os_admin_password', 'climate.config')
CONF.import_opt('os_admin_tenant_name', 'climate.config')
CONF.import_opt('os_admin_project_name', 'climate.config')
CONF.import_opt('os_auth_version', 'climate.config')
CONF.import_opt('log_exchange', 'climate.config')
@ -99,7 +99,7 @@ def make_app():
auth_protocol=cfg.CONF.os_auth_protocol,
admin_user=cfg.CONF.os_admin_username,
admin_password=cfg.CONF.os_admin_password,
admin_tenant_name=cfg.CONF.os_admin_tenant_name,
admin_tenant_name=cfg.CONF.os_admin_project_name,
auth_version=cfg.CONF.os_auth_version,
)(app.wsgi_app)

View File

@ -35,10 +35,10 @@ class API(object):
"""List all existing leases."""
ctx = context.current()
if policy.enforce(ctx, 'admin', {}, do_raise=False):
tenant_id = None
project_id = None
else:
tenant_id = ctx.tenant_id
return self.manager_rpcapi.list_leases(tenant_id=tenant_id)
project_id = ctx.project_id
return self.manager_rpcapi.list_leases(project_id=project_id)
@policy.authorize('leases', 'create')
def create_lease(self, data):

View File

@ -44,7 +44,7 @@ class Lease(base._Base):
user_id = types.UuidType()
"The ID of the user who creates the lease"
tenant_id = types.UuidType()
project_id = types.UuidType()
"The ID of the project or tenant the lease belongs to"
trust_id = types.UuidType()
@ -63,7 +63,7 @@ class Lease(base._Base):
start_date=u'2014-01-01 01:23',
end_date=u'2014-02-01 13:37',
user_id=u'efd87807-12d2-4b38-9c70-5f5c2ac427ff',
tenant_id=u'bd9431c1-8d69-4ad3-803a-8d4a6b89fd36',
project_id=u'bd9431c1-8d69-4ad3-803a-8d4a6b89fd36',
trust_id=u'35b17138-b364-4e6a-a131-8f3099c5be68',
reservations=[{u'resource_id': u'1234',
u'resource_type': u'virtual:instance'}],

View File

@ -43,14 +43,14 @@ os_opts = [
cfg.StrOpt('os_admin_username',
default='admin',
help='This OpenStack user is used to verify provided tokens. '
'The user must have admin role in <os_admin_tenant_name> '
'tenant'),
'The user must have admin role in <os_admin_project_name> '
'project'),
cfg.StrOpt('os_admin_password',
default='climate',
help='Password of the admin user'),
cfg.StrOpt('os_admin_tenant_name',
cfg.StrOpt('os_admin_project_name',
default='admin',
help='Name of tenant where the user is admin'),
help='Name of project where the user is admin'),
cfg.StrOpt('os_auth_version',
default='v2.0',
help='We use API v3 to allow trusts using.'),

View File

@ -81,11 +81,11 @@ class ClimateContext(BaseContext):
_elements = set([
"user_id",
"tenant_id",
"project_id",
"auth_token",
"service_catalog",
"user_name",
"tenant_name",
"project_name",
"roles",
"is_admin",
])

View File

@ -156,9 +156,9 @@ def lease_get_all():
@to_dict
def lease_get_all_by_tenant(tenant_id):
"""Return all leases in specific tenant."""
return IMPL.lease_get_all_by_tenant(tenant_id)
def lease_get_all_by_project(project_id):
"""Return all leases in specific project."""
return IMPL.lease_get_all_by_project(project_id)
@to_dict
@ -174,9 +174,9 @@ def lease_get(lease_id):
@to_dict
def lease_list(tenant_id=None):
def lease_list(project_id=None):
"""Return a list of all existing leases."""
return IMPL.lease_list(tenant_id)
return IMPL.lease_list(project_id)
def lease_destroy(lease_id):

View File

@ -0,0 +1,59 @@
# Copyright 2014 OpenStack Foundation.
#
# 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.
"""Change tenant to project
Revision ID: 2bcfe76b0474
Revises: 0_1
Create Date: 2014-03-19 18:08:50.825586
"""
# revision identifiers, used by Alembic.
revision = '2bcfe76b0474'
down_revision = '10e34bba18e8'
from alembic import op
import sqlalchemy as sa
def upgrade():
engine = op.get_bind().engine
if engine.name == 'sqlite':
# Only for testing purposes with sqlite
op.execute('CREATE TABLE tmp_leases as SELECT created_at, updated_at, '
'id, name, user_id, tenant_id as project_id, start_date, '
'end_date, trust_id FROM leases')
op.execute('DROP TABLE leases')
op.execute('ALTER TABLE tmp_leases RENAME TO leases')
return
op.alter_column('leases', 'tenant_id', name='project_id',
existing_type=sa.String(length=255))
def downgrade():
engine = op.get_bind().engine
if engine.name == 'sqlite':
# Only for testing purposes with sqlite
op.execute('CREATE TABLE tmp_leases as SELECT created_at, updated_at, '
'id, name, user_id, project_id as tenant_id, start_date, '
'end_date, trust_id FROM leases')
op.execute('DROP TABLE leases')
op.execute('ALTER TABLE tmp_leases RENAME TO leases')
return
op.alter_column('leases', 'project_id', name='tenant_id',
existing_type=sa.String(length=255))

View File

@ -48,7 +48,7 @@ def model_query(model, session=None):
:param model: base model to query
:param project_only: if present and current context is user-type,
then restrict query to match the tenant_id from current context.
then restrict query to match the project_id from current context.
"""
session = session or get_session()
@ -207,7 +207,7 @@ def lease_get_all():
return query.all()
def lease_get_all_by_tenant(tenant_id):
def lease_get_all_by_project(project_id):
raise NotImplementedError
@ -215,10 +215,10 @@ def lease_get_all_by_user(user_id):
raise NotImplementedError
def lease_list(tenant_id=None):
def lease_list(project_id=None):
query = model_query(models.Lease, get_session())
if tenant_id is not None:
query = query.filter_by(tenant_id=tenant_id)
if project_id is not None:
query = query.filter_by(project_id=project_id)
return query.all()

View File

@ -56,7 +56,7 @@ class Lease(mb.ClimateBase):
id = _id_column()
name = sa.Column(sa.String(80), nullable=False)
user_id = sa.Column(sa.String(255), nullable=True)
tenant_id = sa.Column(sa.String(255), nullable=True)
project_id = sa.Column(sa.String(255), nullable=True)
start_date = sa.Column(sa.DateTime, nullable=False)
end_date = sa.Column(sa.DateTime, nullable=False)
trust_id = sa.Column(sa.String(36))

View File

@ -30,9 +30,9 @@ class ManagerRPCAPI(service.RPCClient):
"""Get detailed info about some lease."""
return self.call('get_lease', lease_id=lease_id)
def list_leases(self, tenant_id=None):
def list_leases(self, project_id=None):
"""List all leases."""
return self.call('list_leases', tenant_id=tenant_id)
return self.call('list_leases', project_id=project_id)
def create_lease(self, lease_values):
"""Create lease with specified parameters."""

View File

@ -153,8 +153,8 @@ class ManagerService(service_utils.RPCServer):
def get_lease(self, lease_id):
return db_api.lease_get(lease_id)
def list_leases(self, tenant_id=None):
return db_api.lease_list(tenant_id)
def list_leases(self, project_id=None):
return db_api.lease_list(project_id)
def create_lease(self, lease_values):
"""Create a lease with reservations.
@ -186,7 +186,7 @@ class ManagerService(service_utils.RPCServer):
ctx = context.current()
lease_values['user_id'] = ctx.user_id
lease_values['tenant_id'] = ctx.tenant_id
lease_values['project_id'] = ctx.project_id
lease_values['start_date'] = start_date
lease_values['end_date'] = end_date

View File

@ -24,9 +24,9 @@ admin_opts = [
cfg.StrOpt('climate_password',
default='climate_password',
help='Password of the user for write operations'),
cfg.StrOpt('climate_tenant_name',
cfg.StrOpt('climate_project_name',
default='admin',
help='Tenant of the user for write operations'),
help='Project of the user for write operations'),
]
cfg.CONF.register_opts(admin_opts, group=RESOURCE_TYPE)

View File

@ -63,7 +63,7 @@ class PhysicalHostPlugin(base.BasePlugin, nova.NovaClientWrapper):
config = cfg.CONF[self.resource_type]
self.username = config.climate_username
self.api_key = config.climate_password
self.project_id = config.climate_tenant_name
self.project_id = config.climate_project_name
def create_reservation(self, values):
"""Create reservation."""

View File

@ -32,7 +32,7 @@ class NovaInventory(nova.NovaClientWrapper):
config = cfg.CONF[plugin.RESOURCE_TYPE]
self.username = config.climate_username
self.api_key = config.climate_password
self.project_id = config.climate_tenant_name
self.project_id = config.climate_project_name
def get_host_details(self, host):
"""Get Nova capabilities of a single host

View File

@ -33,12 +33,12 @@ OPTS = [
default='freepool',
help='Name of the special aggregate where all hosts '
'are candidate for physical host reservation'),
cfg.StrOpt('tenant_id_key',
default='climate:tenant',
help='Aggregate metadata value for key matching tenant_id'),
cfg.StrOpt('project_id_key',
default='climate:project',
help='Aggregate metadata value for key matching project_id'),
cfg.StrOpt('climate_owner',
default='climate:owner',
help='Aggregate metadata key for knowing owner tenant_id'),
help='Aggregate metadata key for knowing owner project_id'),
cfg.StrOpt('climate_az_prefix',
default='climate:',
help='Prefix for Availability Zones created by Climate'),
@ -59,7 +59,7 @@ class ReservationPool(nova.NovaClientWrapper):
config = cfg.CONF[plugin.RESOURCE_TYPE]
self.username = config.climate_username
self.api_key = config.climate_password
self.project_id = config.climate_tenant_name
self.project_id = config.climate_project_name
def get_aggregate_from_name_or_id(self, aggregate_obj):
"""Return an aggregate by name or an id."""
@ -115,7 +115,7 @@ class ReservationPool(nova.NovaClientWrapper):
'without Availability Zone' % name)
agg = self.nova.aggregates.create(name, None)
meta = {self.config.climate_owner: self.ctx.tenant_id}
meta = {self.config.climate_owner: self.ctx.project_id}
self.nova.aggregates.set_metadata(agg, meta)
return agg
@ -262,7 +262,7 @@ class ReservationPool(nova.NovaClientWrapper):
def add_project(self, pool, project_id):
"""Add a project to an aggregate."""
metadata = {project_id: self.config.tenant_id_key}
metadata = {project_id: self.config.project_id_key}
agg = self.get_aggregate_from_name_or_id(pool)

View File

@ -66,7 +66,7 @@ def enforce(context, action, target, do_raise=True):
``volume:attach_volume``
:param target: dictionary representing the object of the action
for object creation this should be a dictionary representing the
location of the object e.g. ``{'tenant_id': context.tenant_id}``
location of the object e.g. ``{'project_id': context.project_id}``
:param do_raise: if True (the default), raises PolicyNotAuthorized;
if False, returns False
@ -98,7 +98,7 @@ def authorize(extension, action=None, api='climate', ctx=None,
@functools.wraps(func)
def wrapped(self, *args, **kwargs):
cur_ctx = ctx or context.current()
tgt = target or {'tenant_id': cur_ctx.tenant_id,
tgt = target or {'project_id': cur_ctx.project_id,
'user_id': cur_ctx.user_id}
if action is None:
act = '%s:%s' % (api, extension)

View File

@ -40,15 +40,15 @@ class APITest(tests.TestCase):
def fake_ctx_from_headers(headers):
if not headers:
return context.ClimateContext(
user_id='fake', tenant_id='fake', roles=['member'])
user_id='fake', project_id='fake', roles=['member'])
roles = headers.get('X-Roles', six.text_type('member')).split(',')
return context.ClimateContext(
user_id=headers.get('X-User-Id', 'fake'),
tenant_id=headers.get('X-Tenant-Id', 'fake'),
project_id=headers.get('X-Project-Id', 'fake'),
auth_token=headers.get('X-Auth-Token', None),
service_catalog=None,
user_name=headers.get('X-User-Name', 'fake'),
tenant_name=headers.get('X-Tenant-Name', 'fake'),
project_name=headers.get('X-Project-Name', 'fake'),
roles=roles,
)

View File

@ -26,10 +26,10 @@ class ContextTestCase(tests.TestCase):
super(ContextTestCase, self).setUp()
self.fake_headers = {u'X-User-Id': u'1',
u'X-Tenant-Id': u'1',
u'X-Project-Id': u'1',
u'X-Auth-Token': u'111-111-111',
u'X-User-Name': u'user_name',
u'X-Tenant-Name': u'tenant_name',
u'X-Project-Name': u'project_name',
u'X-Roles': u'user_name0, user_name1'}
def test_ctx_from_headers(self):
@ -40,11 +40,11 @@ class ContextTestCase(tests.TestCase):
self.context.assert_called_once_with(user_id=u'1',
roles=[u'user_name0',
u'user_name1'],
tenant_name=u'tenant_name',
project_name=u'project_name',
auth_token=u'111-111-111',
service_catalog={
u'nova': u'catalog'},
tenant_id=u'1',
project_id=u'1',
user_name=u'user_name')
def test_ctx_from_headers_no_catalog(self):

View File

@ -32,8 +32,8 @@ def fake_lease(**kw):
u'trust_id': kw.get('trust_id',
u'35b17138-b364-4e6a-a131-8f3099c5be68'),
u'user_id': kw.get('user_id', u'efd87807-12d2-4b38-9c70-5f5c2ac427ff'),
u'tenant_id': kw.get('tenant_id',
u'bd9431c1-8d69-4ad3-803a-8d4a6b89fd36'),
u'project_id': kw.get('project_id',
u'bd9431c1-8d69-4ad3-803a-8d4a6b89fd36'),
u'reservations': kw.get('reservations', [
{
u'resource_id': u'1234',
@ -48,7 +48,7 @@ def fake_lease_request_body(exclude=[], **kw):
exclude.append('id')
exclude.append('trust_id')
exclude.append('user_id')
exclude.append('tenant_id')
exclude.append('project_id')
lease_body = fake_lease(**kw)
return dict((key, lease_body[key])
for key in lease_body if key not in exclude)

View File

@ -115,3 +115,7 @@ class TestMigrations(migration.BaseWalkMigrationTestCase,
def _check_10e34bba18e8(self, engine, data):
self.assertColumnExists(engine, 'computehosts', 'service_name')
def _check_2bcfe76b0474(self, engine, data):
self.assertColumnExists(engine, 'leases', 'project_id')
self.assertColumnNotExists(engine, 'leases', 'tenant_id')

View File

@ -79,7 +79,7 @@ def _get_fake_virt_lease_values(id=_get_fake_lease_uuid(),
return {'id': id,
'name': name,
'user_id': _get_fake_random_uuid(),
'tenant_id': _get_fake_random_uuid(),
'project_id': _get_fake_random_uuid(),
'start_date': start_date,
'end_date': end_date,
'trust': 'trust',
@ -98,7 +98,7 @@ def _get_fake_phys_lease_values(id=_get_fake_lease_uuid(),
return {'id': id,
'name': name,
'user_id': 'fake',
'tenant_id': 'fake',
'project_id': 'fake',
'start_date': start_date,
'end_date': end_date,
'trust': 'trust',

View File

@ -17,7 +17,7 @@ policy_data = """
{
"admin": "is_admin:True or role:admin or role:masterofuniverse",
"admin_or_owner": "rule:admin or tenant_id:%(tenant_id)s",
"admin_or_owner": "rule:admin or project_id:%(project_id)s",
"default": "!",
"admin_api": "rule:admin",

View File

@ -36,7 +36,7 @@ class RPCAPITestCase(tests.TestCase):
def test_list_leases(self):
self.manager.list_leases('fake')
self.call.assert_called_once_with('list_leases', tenant_id='fake')
self.call.assert_called_once_with('list_leases', project_id='fake')
def test_create_lease(self):
self.manager.create_lease(self.fake_values)

View File

@ -40,13 +40,13 @@ class ReservationPoolTestCase(tests.TestCase):
def setUp(self):
super(ReservationPoolTestCase, self).setUp()
self.pool_name = 'pool-name-xxx'
self.tenant_id = 'tenant-uuid'
self.project_id = 'project-uuid'
self.fake_aggregate = AggregateFake(i=123,
name='fooname',
hosts=['host1', 'host2'])
conf = cfg.CONF[host_plugin.RESOURCE_TYPE]
self.freepool_name = conf.aggregate_freepool_name
self.tenant_id_key = conf.tenant_id_key
self.project_id_key = conf.project_id_key
self.climate_owner = conf.climate_owner
self.climate_az_prefix = conf.climate_az_prefix
@ -54,7 +54,7 @@ class ReservationPoolTestCase(tests.TestCase):
name=self.freepool_name,
hosts=['host3'])
self.set_context(context.ClimateContext(tenant_id=self.tenant_id))
self.set_context(context.ClimateContext(project_id=self.project_id))
self.nova_client = nova_client
self.nova = self.patch(self.nova_client, 'Client').return_value
@ -115,7 +115,7 @@ class ReservationPoolTestCase(tests.TestCase):
self.nova.aggregates.create\
.assert_called_once_with(self.pool_name, az_name)
meta = {self.climate_owner: self.tenant_id}
meta = {self.climate_owner: self.project_id}
self.nova.aggregates.set_metadata\
.assert_called_once_with(self.fake_aggregate, meta)
@ -311,7 +311,7 @@ class ReservationPoolTestCase(tests.TestCase):
self.pool.add_project('pool', 'projectX')
self.nova.aggregates.set_metadata\
.assert_called_once_with(self.fake_aggregate.id,
{'projectX': self.tenant_id_key})
{'projectX': self.project_id_key})
def test_remove_project(self):
self._patch_get_aggregate_from_name_or_id()

View File

@ -97,8 +97,8 @@ class TestClimateContext(tests.TestCase):
self.assertEqual(ctx.is_admin, True)
def test_elevated(self):
with context.ClimateContext(user_id="user", tenant_id="tenant"):
with context.ClimateContext(user_id="user", project_id="project"):
ctx = context.ClimateContext.elevated()
self.assertEqual(ctx.user_id, "user")
self.assertEqual(ctx.tenant_id, "tenant")
self.assertEqual(ctx.project_id, "project")
self.assertEqual(ctx.is_admin, True)

View File

@ -36,14 +36,15 @@ class DefaultPolicyTestCase(tests.TestCase):
"example:exist": "!",
"example:allowed": "@",
"example:my_file": "role:admin or \
tenant_id:%(tenant_id)s"
project_id:%(project_id)s"
}
"""
self.default_rule = None
policy.reset()
self.read_cached_file.return_value = (True, self.rules)
self.context = context.ClimateContext(user_id='fake', tenant_id='fake',
self.context = context.ClimateContext(user_id='fake',
project_id='fake',
roles=['member'])
def _set_rules(self, default_rule):
@ -69,8 +70,8 @@ class DefaultPolicyTestCase(tests.TestCase):
self.assertEqual(result, True)
def test_templatized_enforcement(self):
target_mine = {'tenant_id': 'fake'}
target_not_mine = {'tenant_id': 'another'}
target_mine = {'project_id': 'fake'}
target_not_mine = {'project_id': 'another'}
action = "example:my_file"
policy.enforce(self.context, action, target_mine)
self.assertRaises(exceptions.PolicyNotAuthorized, policy.enforce,
@ -82,14 +83,15 @@ class ClimatePolicyTestCase(tests.TestCase):
def setUp(self):
super(ClimatePolicyTestCase, self).setUp()
self.context = context.ClimateContext(user_id='fake', tenant_id='fake',
self.context = context.ClimateContext(user_id='fake',
project_id='fake',
roles=['member'])
def test_standardpolicy(self):
target_good = {'user_id': self.context.user_id,
'tenant_id': self.context.tenant_id}
'project_id': self.context.project_id}
target_wrong = {'user_id': self.context.user_id,
'tenant_id': 'bad_tenant'}
'project_id': 'bad_project'}
action = "climate:leases"
self.assertEqual(True, policy.enforce(self.context, action,
target_good))
@ -98,14 +100,14 @@ class ClimatePolicyTestCase(tests.TestCase):
def test_adminpolicy(self):
target = {'user_id': self.context.user_id,
'tenant_id': self.context.tenant_id}
'project_id': self.context.project_id}
action = "climate:oshosts"
self.assertRaises(exceptions.PolicyNotAuthorized, policy.enforce,
self.context, action, target)
def test_elevatedpolicy(self):
target = {'user_id': self.context.user_id,
'tenant_id': self.context.tenant_id}
'project_id': self.context.project_id}
action = "climate:oshosts"
self.assertRaises(exceptions.PolicyNotAuthorized, policy.enforce,
self.context, action, target)

View File

@ -39,7 +39,7 @@ class TestCKClient(tests.TestCase):
self.username = 'fake_user'
self.token = 'fake_token'
self.password = 'fake_pass'
self.tenant_name = 'fake_tenant'
self.tenant_name = 'fake_project'
self.auth_url = 'fake_url'
self.trust_id = 'fake_trust'
@ -79,12 +79,13 @@ class TestCKClient(tests.TestCase):
self.keystone.ClimateKeystoneClient()
self.client.assert_called_once_with(version='3',
username=self.ctx().user_name,
token=self.ctx().auth_token,
tenant_name=self.ctx().tenant_name,
auth_url='http://fake.com/',
endpoint='http://fake.com/')
self.client.assert_called_once_with(
version='3',
username=self.ctx().user_name,
token=self.ctx().auth_token,
tenant_name=self.ctx().project_name,
auth_url='http://fake.com/',
endpoint='http://fake.com/')
def test_getattr(self):
#TODO(n.s.): Will be done as soon as pypi package will be updated

View File

@ -37,7 +37,7 @@ class TestCNClient(tests.TestCase):
self.version = '2'
self.username = 'fake_user'
self.api_key = self.ctx().auth_token
self.project_id = self.ctx().tenant_id
self.project_id = self.ctx().project_id
self.auth_url = 'fake_auth'
self.mgmt_url = 'fake_mgmt'
@ -68,7 +68,7 @@ class TestCNClient(tests.TestCase):
self.client.assert_called_once_with(version=self.version,
username=self.ctx().user_name,
api_key=None,
project_id=self.ctx().tenant_id,
project_id=self.ctx().project_id,
auth_url='http://fake.com/')
def test_getattr(self):

View File

@ -54,8 +54,8 @@ class TestTrusts(tests.TestCase):
fake_ctx_dict = {'_BaseContext__values': {
'auth_token': self.client().auth_token,
'service_catalog': fake_item,
'tenant_id': self.client().tenant_id,
'tenant_name': 'admin',
'project_id': self.client().tenant_id,
'project_name': 'admin',
'user_name': 'admin',
}}

View File

@ -86,7 +86,7 @@ class ClimateKeystoneClient(object):
kwargs.setdefault('version', cfg.CONF.keystone_client_version)
if ctx is not None:
kwargs.setdefault('username', ctx.user_name)
kwargs.setdefault('tenant_name', ctx.tenant_name)
kwargs.setdefault('tenant_name', ctx.project_name)
if not kwargs.get('auth_url'):
kwargs['auth_url'] = base.url_for(
ctx.service_catalog, CONF.identity_service)

View File

@ -80,7 +80,7 @@ class ClimateNovaClient(object):
if ctx is not None:
kwargs.setdefault('username', ctx.user_name)
kwargs.setdefault('api_key', None)
kwargs.setdefault('project_id', ctx.tenant_id)
kwargs.setdefault('project_id', ctx.project_id)
kwargs.setdefault('auth_url', base.url_for(
ctx.service_catalog, CONF.identity_service))

View File

@ -28,14 +28,14 @@ def create_trust():
trustee_id = keystone.ClimateKeystoneClient(
username=CONF.os_admin_username,
password=CONF.os_admin_password,
tenant_name=CONF.os_admin_tenant_name).user_id
tenant_name=CONF.os_admin_project_name).user_id
ctx = context.current()
trust = client.trusts.create(trustor_user=ctx.user_id,
trustee_user=trustee_id,
impersonation=False,
role_names=ctx.roles,
project=ctx.tenant_id)
project=ctx.project_id)
return trust
@ -50,7 +50,7 @@ def create_ctx_from_trust(trust_id):
"""Return context built from given trust."""
ctx = context.ClimateContext(
user_name=CONF.os_admin_username,
tenant_name=CONF.os_admin_tenant_name,
project_name=CONF.os_admin_project_name,
)
auth_url = "%s://%s:%s/v3" % (CONF.os_auth_protocol,
CONF.os_auth_host,
@ -67,5 +67,5 @@ def create_ctx_from_trust(trust_id):
ctx,
auth_token=client.auth_token,
service_catalog=client.service_catalog.catalog['catalog'],
tenant_id=client.tenant_id,
project_id=client.tenant_id,
)

View File

@ -83,11 +83,11 @@ function configure_climate() {
iniset $CLIMATE_CONF_FILE DEFAULT os_auth_port $KEYSTONE_SERVICE_PORT
iniset $CLIMATE_CONF_FILE DEFAULT os_admin_password $SERVICE_PASSWORD
iniset $CLIMATE_CONF_FILE DEFAULT os_admin_username climate
iniset $CLIMATE_CONF_FILE DEFAULT os_admin_tenant_name $SERVICE_TENANT_NAME
iniset $CLIMATE_CONF_FILE DEFAULT os_admin_project_name $SERVICE_TENANT_NAME
iniset $CLIMATE_CONF_FILE physical:host climate_username $CLIMATE_USER_NAME
iniset $CLIMATE_CONF_FILE physical:host climate_password $SERVICE_PASSWORD
iniset $CLIMATE_CONF_FILE physical:host climate_tenant_name $SERVICE_TENANT_NAME
iniset $CLIMATE_CONF_FILE physical:host climate_project_name $SERVICE_TENANT_NAME
iniset $CLIMATE_CONF_FILE physical:host aggregate_freepool_name $CLIMATE_FREEPOOL_NAME
iniset $CLIMATE_CONF_FILE DEFAULT host $HOST_IP

View File

@ -4,7 +4,7 @@ Introduction
Idea of creating Climate originated with two different use cases:
* Compute host reservation (when user with admin privileges can reserve
hardware resources that are dedicated to the sole use of a tenant)
hardware resources that are dedicated to the sole use of a project)
* Virtual machine (instance) reservation (when user may ask reservation service
to provide him working VM not necessary now, but also in the future)
@ -79,7 +79,7 @@ Lease types (concepts)
cannot be fulfilled immediately. Best-effort mechanism starts something like
scavenger hunt trying to find resources for reservations. For compute hosts
reservation that makes much sense, because in case there are instances
belonging to other tenant on eligible hosts, and without them there will be
belonging to other project on eligible hosts, and without them there will be
possible to reserve these hosts, Climate may start instances migration.
This operation can be timely and fairly complex and so different strategies
may be applied depending on heuristic factors such as the number, type and

View File

@ -114,7 +114,7 @@ are mentioned.
}
],
"start_date": "1234",
"tenant_id": "tenant_id",
"project_id": "project_id",
"trust_id": "trust_id",
"updated_at": null,
"user_id": "user_id"
@ -198,7 +198,7 @@ are mentioned.
}
],
"start_date": "1234",
"tenant_id": "tenant_id",
"project_id": "project_id",
"trust_id": "trust_id",
"updated_at": null,
"user_id": "user_id"
@ -266,7 +266,7 @@ are mentioned.
}
],
"start_date": "1234",
"tenant_id": "tenant_id",
"project_id": "project_id",
"trust_id": "trust_id",
"updated_at": null,
"user_id": "user_id"
@ -341,7 +341,7 @@ are mentioned.
}
],
"start_date": "1234",
"tenant_id": "tenant_id",
"project_id": "project_id",
"trust_id": "trust_id",
"updated_at": null,
"user_id": "user_id"

View File

@ -94,7 +94,7 @@ file using the following example:
os_auth_protocol=<http, for example>
os_admin_username=<username>
os_admin_password=<password>
os_admin_tenant_name=<tenant_name>
os_admin_project_name=<project_name>
[manager]
plugins=basic.vm.plugin,physical.host.plugin
@ -108,7 +108,7 @@ file using the following example:
on_end=on_end
climate_username=<username>
climate_password=<password>
climate_tenant_name=<tenant_name>
climate_project_name=<project_name>
..

View File

@ -220,15 +220,15 @@
#os_auth_port=35357
# This OpenStack user is used to verify provided tokens. The
# user must have admin role in <os_admin_tenant_name> tenant
# user must have admin role in <os_admin_project_name> project
# (string value)
#os_admin_username=admin
# Password of the admin user (string value)
#os_admin_password=climate
# Name of tenant where the user is admin (string value)
#os_admin_tenant_name=admin
# Name of project where the user is admin (string value)
#os_admin_project_name=admin
# We use API v3 to allow trusts using. (string value)
#os_auth_version=v2.0
@ -556,24 +556,30 @@
# Options defined in keystoneclient.middleware.auth_token
#
# Prefix to prepend at the beginning of the path (string
# value)
# Prefix to prepend at the beginning of the path. Deprecated,
# use identity_uri. (string value)
#auth_admin_prefix=
# Host providing the admin Identity API endpoint (string
# value)
# Host providing the admin Identity API endpoint. Deprecated,
# use identity_uri. (string value)
#auth_host=127.0.0.1
# Port of the admin Identity API endpoint (integer value)
# Port of the admin Identity API endpoint. Deprecated, use
# identity_uri. (integer value)
#auth_port=35357
# Protocol of the admin Identity API endpoint(http or https)
# (string value)
# Protocol of the admin Identity API endpoint (http or https).
# Deprecated, use identity_uri. (string value)
#auth_protocol=https
# Complete public Identity API endpoint (string value)
#auth_uri=<None>
# Complete admin Identity API endpoint. This should specify
# the unversioned root endpoint eg. https://localhost:35357/
# (string value)
#identity_uri=<None>
# API version of the admin Identity API endpoint (string
# value)
#auth_version=<None>
@ -722,8 +728,8 @@
# Password of the user for write operations (string value)
#climate_password=climate_password
# Tenant of the user for write operations (string value)
#climate_tenant_name=admin
# Project of the user for write operations (string value)
#climate_project_name=admin
#
@ -743,11 +749,11 @@
# for physical host reservation (string value)
#aggregate_freepool_name=freepool
# Aggregate metadata value for key matching tenant_id (string
# Aggregate metadata value for key matching project_id (string
# value)
#tenant_id_key=climate:tenant
#project_id_key=climate:project
# Aggregate metadata key for knowing owner tenant_id (string
# Aggregate metadata key for knowing owner project_id (string
# value)
#climate_owner=climate:owner

View File

@ -1,7 +1,7 @@
{
"admin": "is_admin:True or role:admin or role:masterofuniverse",
"admin_or_owner": "rule:admin or tenant_id:%(tenant_id)s",
"admin_or_owner": "rule:admin or project_id:%(project_id)s",
"default": "!",
"admin_api": "rule:admin",